我的系统对其所做的事情有严格的“一次且一次”要求。它是一个带有中间件的事件驱动系统,它不能保证只发送一次消息(如果对这是否是重新发送有疑问,它会将任何给定消息标记为“重新发送”)。 “一次且仅一次”处理基本上归结为我们的核心域对象的状态,即它是一个相当标准的设置,即....
3必须最终打到一个数据库(书籍和记录),4可以采取各种形式,但都是对外部系统的某种消息。还有其他各种流程,但它们都归结为这种处理方式。所有消息都将在核心域对象的单个实例上运行,因此处理可以将该实例固定到单个jvm。
我的Q很通用,可能太笼统但我还是会问。即,在保持所需保证的同时,可以采用哪些策略/模式来提高吞吐量?或者,会破坏性能的主要问题是什么?
例如,一种思路就是避免在关键路径中存在任何持久性,这一问题归结为如何保持内存状态的一致性而无需从数据库刷新。
您可以假设可以通过某种分区策略进行扩展,但该方面超出了q的范围。 Q是关于如何在这样的系统中扩大单个节点的吞吐量。
请注意,这是一个大型企业设置中的java / oracle,因此小众硬件(例如exadata和朋友或某些花哨的网络套件)都可以。
答案 0 :(得分:2)
很大程度上取决于您在如何处理故障方面需要什么保证。使用平面日志文件和/或冗余服务器来实现持久性,您可以实现每秒超过一百万的消息传递速率。
您需要的主要模式是演员模式。要提高吞吐量,您需要能够透明地批量处理数据,作为设计的一部分。我个人喜欢使用直接ByteBuffers(大多数数据不在堆上),因为它们是处理大量数据的轻量级方法,可以轻松地复制和读取/写入NIO通道。我为gc-less输入/输出编写了自己的解析/日志记录库。
另一个有用的策略是预分配和回收对象。这可以通过不产生垃圾(或仅创建可以每天收集一次的非常少量)来帮助消除GC的风险。
技巧不是在满足持久性保证之前发布处理结果。 (最简单的方法是没有任何保证,并说最后几笔交易可能会丢失并将手动处理)
可以扼杀性能的主要因素是
答案 1 :(得分:1)
不确定我是否可以轻松地将此问题与您提到的"once and only once" requirements
相关联,但无论如何我都会试一试。
事件驱动/非阻止方法,我认为在messages arrive
评判的流程中已经“有点”了。想象一下自包含/不可变组件能够接收消息并根据消息的类型/有效负载做出反应,让我们暂时调用这些组件actors
。然后你的流程就会变成:
演员
在与该消息的类型
对应/匹配的无状态method
中
state
可以是平面文件/ RDBMS / NoSQL /内存,仅取决于您的架构=>这是由业务驱动的。
因此,相同的method
可以调用store.update()
或者只是向StatusActor发送另一条消息(例如UpdateStatus),因此我们不会锁定/阻止[这取决于“update => ; generate =>发送下游“需要是原子的还是非原子的”
现在,actor向另一个生成输出的actor发送另一条消息(例如GenerateOutput),并向另一个actor发送另一条消息(例如SendDownstream)。
阻止/锁定和......过早优化
答案 2 :(得分:0)
这是“相当”容易,“只是”使您的操作具有幂等性并且可以完成所有操作。