由于性能原因,我们的系统具有完全保留在内存中的结构化模型(大约30个具有多种关系的不同实体)(大约10 Gb)。 在这个模型上我们必须做3种操作:
目前,该体系结构是一个相当标准的体系结构,具有使用共享模型的servlet的线程池。 在模型内部有很多并发集合,但仍然有许多等待,因为一些实体“更热”,并且大多数线程想要读/写它们。 另请注意,通常查询比写入更耗费cpu和时间。
我正在研究切换到Disruptor架构的可能性,将模型保存在一个线程中,在一个单独的消费者中将所有可能的(有效性检查,审核等)移出模型。
第一个问题当然是:它有意义吗?
Secondo问题是:理想情况下,写入请求应优先于读取请求。在disruptor中优先考虑哪种方式?我正在考虑使用2个环缓冲区,然后尝试从高优先级读取,而不是从低优先级读取。
澄清这个问题比LMAX Disruptor的实际代码更具架构性。
更新详情
数据是一个复杂的域,许多不同类型(~20)的许多实体(> 100k)在具有许多不同集合的树结构中链接在它们之间。
查询通常涉及遍历数千个实体以查找正确的数据。 更新频繁但非常有限,比如10个实体,因此整个数据的变化不大(例如每小时20%)。
我做了一些初步测试,看起来并行查询模型的速度优势超过了偶尔的写锁延迟。
答案 0 :(得分:2)
LMAX可能是合适的..
LMAX人首先实施传统,然后他们实施了演员(有队列)并且发现演员大部分时间都在队列中度过。然后他们进入单线程架构。现在,破坏者不是架构的关键,关键是单线程BL。使用1个编写器(单线程)和小对象,您将获得高缓存命中并且没有争用。为此,他们必须将所有长时间运行的代码移出业务层(包括IO)。现在要做到这一点,他们使用它们使用破坏器它基本上只是一个带有单个写入器的环形缓冲区,因为已经在设备驱动程序代码中使用了一段时间但是在一个巨大的消息规模。
首先我对此有一个不同意见,LMAX是一个演员系统..你有一个演员为所有的BL(和破坏者连接其他演员)..他们可以有显着改善演员系统,而不是跳到1 BL的演员,即
对于这些演员,你有一个更模块化的(因此主表)系统(并且系统可以启动更多演员来处理队列 - 注意1作者!)
根据你的情况我认为一小时内20%的变化是巨大的...查询是否始终在内存对象中?你有内存哈希表/索引吗?你能用只读集吗?如果您的数据是旧的,这是否重要,例如Ebay在其商品集合上使用1小时刷新,因此商品集合本身是静态的。通过静态集合和静态项目简介,它们具有静态索引,您可以快速搜索和查找项目以及所有内存。它每小时重建一次,完成后(可能需要几分钟才能重建),系统会切换到新数据。请注意,项目本身不是静态的。
在您拥有庞大域名的情况下,单个线程可能会获得较低的缓存命中率......这与LMAX的不同之处在于,每个邮件都有较小的域名可以传递...
基于代理的系统可能是最好的选择,因为可以对一堆实体进行分组,因此具有高缓存命中率。但我需要了解更多。例如,移动有效性检查,审计,记录等可能是一个很好的计划。更少的代码=更小的对象=更高的缓存命中和LMAX对象很小。
希望这种快速转储有所帮助,但难以理解。
答案 1 :(得分:2)
“理想情况下,写入请求应优先于读取请求。”
为什么?像C#ReaderWriterLockSlim这样的大多数快速锁定都是相反的。写入需要阻止所有读取以避免部分读取。因此,这样的锁允许许多并发读取,希望事情变得“完全”,然后执行写入...(写入确实在队列中的数字上运行,但很可能是在锁定之前处理它之后的许多读取).. < / p>
优先写入是一种杀死并发的好方法。
最终并发/ CQRS是一个选项吗?