相对于无锁技术,Disruptor对于架构思惟的转变,才是其最大亮点。html
说到RingBuffer作的队列,一般都说的是“一读一写“,或者“多读一写“。而Disruptor天生是为“广播“设计,也就是1个Producer,多个Consumer消费同1条消息。服务器
有了“广播“,就能很好的支持不一样逻辑模块的并行计算,从而提升性能。下面会专门分析一个案例,来讨论这个并行计算。网络
假设有以下一个场景: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);
在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