Disruptor-架构思惟的转变

相对于无锁技术,Disruptor对于架构思惟的转变,才是其最大亮点。html

Pub Event

说到RingBuffer作的队列,一般都说的是“一读一写“,或者“多读一写“。而Disruptor天生是为“广播“设计,也就是1个Producer,多个Consumer消费同1条消息。服务器

有了“广播“,就能很好的支持不一样逻辑模块的并行计算,从而提升性能。下面会专门分析一个案例,来讨论这个并行计算。网络

Consumer依赖关系维护

假设有以下一个场景:1个生成者P1,3个消费者C1, C2, C3。其中C3要依赖C1, C2执行完毕。若是基于传统的消息队列来设计,就会是以下的菱形结构:
这里写图片描述架构

之间用4个队列来链接,从P1流经到C3,要通过这4个队列。性能

而若是用Disruptor的话,将只须要一个RingBuffer,3个consumer都消费这同1个RingBuffer,以下图所示:测试

这里写图片描述

在这里,有几个关键点:
(1)C1, C2, C3消费的是同一个RingBuffer,由于进度不同,它们各自有本身的指针,称之为Sequence。这里假设为S1, S2, S3spa

(2)C3是要依赖C1, C2的,也就是它要等C1, C2消费完以后,它才能消费。所以S3取的是Min(S1, S2)。.net

(3)假设P1的指针是S0,P1只须要和S3比较就好了,而不须要和S1, S2比较。由于S3是消费最慢的,只要P1没有跟上S3,那么队列就不会被覆盖。设计

依赖关系的表达

具体到Disruptor中,如何表达C3依赖C1, C2呢?代码举例以下,很简单:指针

//handler1, 2, 3, 4同时消费一个RingBuffer,2, 3, 4并行,同时依赖1 disruptor.handleEventsWith(handler1).then(handler2, handler3, handler4); //handler1,2,3,4同时消费一个RingBuffer,2依赖1,3依赖2,4依赖3 disruptor.handleEventsWith(handler1).then(handler2).then(handler3).then(handler4); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Event Resourcing

在Marin Flower介绍LMAX的价格的时候,http://martinfowler.com/articles/lmax.html

提出了一种思想:Event Resourcing
http://martinfowler.com/eaaDev/EventSourcing.html

下面以LMAX的架构为例,来说解这种思想:
这里写图片描述

如上图所示,Receiver接收请求(这里的Receiver你能够理解为一个网络服务器),BLP处理请求,Publisher把处理结果交给下游。

在这里,BLP是纯粹在内存中操做,那它挂了以后,状态怎么恢复呢?这里有3个关键点:
(1)在BLP处理每个Event以前,该Event先被Journaler日志化
(2)BLP自己是个状态机。即便挂了,能够重放全部日志,恢复状态。另外,为了提升恢复速度,BLP的状态能够按期作Snapshot。
(3)为了提升HA,能够准备多个BLP并行,1个挂了,切换到其它的。因此有一个Replicator组件,用于复制日志。

在这里,Receiver、BLP、Journaler、Replicator经过一个RingBuffer进行交互,以下图所示:

这里写图片描述

在这里有1个Producer,4个Consumer,前3个能够并行,最后一个BLP依赖前3个。

Un-marshaller在这里作一些Event的解析工做。

这种架构还有一个巨大优势就是:可测性。你能够把日志拷贝到测试环境,“重放“整个过程来测试BLP。

总结

经过上面的分析,咱们会发现Disruptor并非咱们一般意义上的一个简单的RingBuffer。

基于它LMAX设计了一个新的架构,这种架构不只速度够快,并且具备持久性、HA、可测性等诸多优势。

--------------------- 本文来自 travi 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/chunlongyu/article/details/53313575?utm_source=copy 

相关文章
相关标签/搜索