当前位置: 首页 > 知识库问答 >
问题:

是否应该将Disruptor(LMAX)与内存中的大型模型和CQR一起使用?

方德宇
2023-03-14

出于性能原因,我们的系统将结构化模型(大约30个不同的实体和几种关系)完全保存在内存中(大约10 Gb)。在这个模型上,我们必须进行3种操作:

  1. 更新一个或几个实体
  2. 查询特定数据(通常需要读取数千个实体)
  3. 获取统计数据(使用了多少内存、查询了多少种类等)

目前,该体系结构是一个相当标准的体系结构,有一个用于使用共享模型的servlet的线程池。在模型内部有很多并发集合,但仍然有很多等待,因为一些实体“更热”,并且大多数线程想要读/写它们。还要注意的是,通常查询比写入要耗费更多的cpu和时间。

我正在研究切换到Disruptor架构的可能性,将模型保持在一个线程中,将所有可能的东西(有效性检查、审计等)移出模型在单独的消费者中。

当然,第一个问题是:这有意义吗?

第二个问题是:理想情况下,写请求应该优先于读请求。在disruptor中拥有优先权的最佳方式是什么?我在考虑2个环形缓冲区,然后尝试更频繁地从高优先级缓冲区读取数据,而不是从低优先级缓冲区读取数据。

澄清这个问题更多的是关于LMAX Disruptor的实际代码。

更新更多详细信息

数据是一个复杂的领域,有许多实体(

查询通常涉及遍历数千个实体以找到正确的数据。更新很频繁,但相当有限,比如一次更新10个实体,所以整个数据变化不大(比如一小时20%)。

我做了一些初步测试,似乎并行查询模型的速度优势超过了偶尔的写锁延迟。

共有2个答案

翟渝
2023-03-14

LMAX可能是合适的。。

LMAX人员首先实现了传统,然后实现了参与者(使用队列),发现参与者大部分时间都在队列中。然后他们转向单线程体系结构。。现在,破坏者不是架构的关键,关键是一个单线程BL。对于1个writer(单线程)和小对象,您将获得高缓存命中率,并且没有争用。要做到这一点,他们必须将所有长期运行的代码移出业务层(包括IO)。现在,为了实现这一点,他们使用了中断器,它基本上只是一个具有单个写入程序的环形缓冲区,就像在设备驱动程序代码中使用的一样,但具有巨大的消息规模。

首先,我不同意这个观点,LMAX是一个演员系统。。在这里,所有BL都有一个参与者(破坏者连接其他参与者)。。他们本可以显著改进there-actor系统,而不是为BL跳到1个actor,即

  1. 不要有太多的服务/参与者,尝试在一个服务中使用常用的组件。(这在SOA/分布式系统中也经常出现)
  2. 在参与者之间进行通信时,使用点对点队列,而不是多对1。(就像所有的服务巴士一样!)
  3. 当您有点对点队列时,请确保尾部是指向单独内存区域的指针。对于2和3,您现在可以使用无锁队列,并且队列/线程只有1个writer(您甚至可以不使用临时256,而是使用YMM位写入队列)。然而,系统现在有更多的线程(如果您正确地执行了1,那么参与者之间的消息量相对较小)。队列类似于中断器,可以批处理许多条目,并且可以使用环形缓冲区样式

有了这些参与者,您就有了一个更模块化的(因此是主表)系统(系统可以启动更多的参与者来处理队列-注1编写器!)

在你的情况下,我认为一小时内20%的更改是巨大的...内存对象中的查询是否始终打开?内存中是否有哈希表/索引?您可以使用只读集合吗?如果您的数据很旧,是否有关系,例如Ebay对其项目集合使用1小时的刷新,因此项目集合本身是静态的。使用静态集合和静态项目简报,它们有一个静态html" target="_blank">索引,您可以在内存中快速搜索和查找项目。每小时它都会被重建,完成后(重建可能需要几分钟)系统会切换到新数据。请注意项目本身不是静态的。

在一个巨大的域中,单个线程的缓存命中率可能很低。。这与LMAX不同,LMAX为每个消息传递一个较小的域。。

基于代理的系统可能是最好的选择,即因为可以对一堆实体进行分组,因此具有高缓存命中率。但我需要知道更多。例如移动有效性检查、审计、日志记录等可能是一个好计划。更少的代码=更小的对象=更高的缓存命中率和LMAX对象很小。

希望这个快速转储有所帮助,但很难只看一眼。

令狐宏浚
2023-03-14

“理想情况下,写请求应优先于读请求。”

为什么?大多数快速锁(如C#ReaderWriterLockSlim)的作用正好相反。。写操作需要阻止所有读取以避免部分读取。因此,这样的锁允许许多并发读取,希望事情变得“安静”,然后再进行写入。。(写入确实在队列中以其编号运行,但很可能在锁定之前处理了许多读取)。。

对写操作进行优先级排序是消除并发性的一种好方法。。

最终并发/CQRS是一种选择吗?

 类似资料:
  • 我们需要运行订单管理器应用程序的Active-Active实例以实现弹性。在我们的团队中,Hazelcast是跨弹性实例共享状态的首选分布式缓存。 在应用程序中,我使用单写入器模式以及LMAX中断器库。因此,基本上我有一个繁忙的主线程,它从中断器(环形缓冲区)读取传入的订单事件,并快速处理它,而不涉及任何阻塞操作。 现在唯一的问题是,只要我的主线程接收到一个事件,它就会首先在Hazelcast分布

  • 问题内容: 我正在尝试将包与我的sequelize模型一起使用,并试图遵循将散列合并到模型中的教程,但是在遇到错误。我似乎无法弄清楚这个问题。有没有更好的方法来合并bcrypt? 错误: 模型: 问题答案: 应在以下方法的“选项”自变量中提供方法

  • Intel内存型号保证: 门店不会与其他门店一起重新订购 货物不会与其他货物一起重新订购 http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/ 我看到有人声称由于英特尔内存模型,SFENCE在x86-64上是多余的,但从来没有LFENCE。上述内存模型规则是否使任一指令冗余?

  • 问题内容: 我在理解Hibernate如何处理泛型时遇到一些麻烦,并且想知道实现我的目标的最佳方法。 给定一个简单的通用实体: 在进行hibernate初始化时,出现异常: 我几乎可以肯定,这是因为我没有给hibernate一些可能的限制条件。我知道你可以指定的东西,如上面的注释,但你失去使用泛型的灵活性。我可以使用注解限制可接受的泛型的范围吗?例如:如果我想要class ,该类从抽象类继承而来,

  • 问题内容: 默认情况下,Hibernate 5不支持PostgreSQL 数据类型。 有什么方法可以实现对Hibernate + Spring JPA的支持? 如果有办法,与Hibernate一起使用的利弊是什么? 问题答案: 感谢Vlad Mihalcea我们有这样的机会!) 他创建了hibernate类型的 lib: 这为Hibernate添加了对’json’,’jsonb’和其他类型的支持:

  • 使用包含Scala和Akka在内的Typesafe平台的主要好处是它简化了并发软件的编写过程。本文将讨论Typesafe平台,尤其是Akka是如何在并发应用中访问共享内存的。 Java内存模型 在Java 5之前,Java内存模型(JMM)定义是有问题的。当多个线程访问共享内存时很可能得到各种奇怪的结果,例如: 一个线程看不到其它线程所写入的值:可见性问题 由于指令没有按期望的顺序执行,一个线程观