Disruptor 介绍
Disruptor 是LMX开源出来的java编写的一个并发消息处理器,在队列中一边生产者放入消息,另外一边消费者并行取出处理,其核心是根据现代CPU硬件缓存特点发明不同于通用LinkedList或Queue的新型数据结构RingBuffer
LMX 系统每秒处理600万订单,这是个神话!,其业务模式是:In Memory+Event Source+Disruptor
Disruptor 框架解决了锁,伪共享带来的性能影响
为什么队列干扰了缓存呢?解释是这样的: 为了将数据放入队列,你需要写入队列,类似地,为了从队列取出数据,你需要移除队列也是一种写,客户端也许不只一次写入同样数据结构,处理写通常需要锁,但是如果锁使用了,会引起切换到底层系统的场景(线程上下文切换—个人理解), 当这个发生后,处理器会丢失它的缓存中的数据。—摘自jdon
关于Disruptor 原理介绍网上很多,可以参考 马丁.福勒 的关于Disruptor 架构介绍,以及其他资料很多的。
Disruptor 使用场景说明
任何一个技术方案都有个使用场景的Disruptor也不例外,此框架的使用场景总结如下:
补充个前提:那就是接到的消息量巨大,如果每秒不上万,十万,百万,那还是不要使用这个框架了,你的消费处理不要太延迟,如果你把这个框架用于往
数据库写数据就不那么适当了。
1、处理CQRS架构风格的command命令(jdon framework底层也是用的disruptor)
2、接收消息并处理场景,如,短信,邮件发送服务
3、业务流水线模式
4、队列使用场景也是Disruptor使用,反过来则未必
Disruptor-net介绍
Disruptor-net 是我在公司利用空余时间把java 版本的Disruptor移植到net 平台上,经过测试后,分享出来,如果有需要的童鞋可以下载下来使用,我上传了全部源码,你也可以修改,但请保留我的博客园地址链接,在使用过程中如果有问题请在博客园回复,我会处理并回复的。
网上有个Disruptor-net项目,这个项目是个老外写的,但目前版本是2.10.0比较老,更新也慢;Disruptor java版本更新很快目前是3.2.0,我的Disruptor-net 也是基于这个版本移植过来的,重用了网上的2.10.0版本的策略调度(对于task及其策略调度网上有个parallel-extensions-extras项目,提供了task及其调度多种算法实现,其实在使用的Disriptor-net 的时候基于策略使用net 默认的就可以了),原子操作两个模块,呵呵,算是资源重用啦,java 版3.2.0 变动很大,很多类名及类的功能与2.10.0完全不一样,增加了多个waitFor策略,ringBuffer也增加很多功能,在移植过程发现java里的接口命名都不加I前缀的,这个看起来很别扭,java 与 NET在具体实现上还是有很大的区别的,其中java里有很多C,C++的影子,java 目前不支持闭包,NET已经开始支持闭包,这在一定程度上提供间接的语法,为了与java版本的保持一致(便于以后升级维护)我在ringBuffer类,只增加了少量的函数闭包风格写法,其他基本上遵循原版的风格(包括注释,我发现eclipse里的java注释,是有格式化而且可以连接跳转,这点比vs里注释友好多了)
基本上主流程上的每个类,都通过功能单元测试,性能单元测试(我使用的是Nunit.net ),感觉比VS 自带的那个测试工具方便点。测试结果是ringBuffer并发处理能力远远超过BlockingCollection的并发处理能力,我的机器是 thinkpad x201i 4核 4G内存,极端情况下4个CPU全部100%,但内存占用量并不大。
性能测试(机器配置 thinkpad x201i 4核 4G内存)
有意思的是,Disrupt-net 测试与Disruptor-Java相差比较大, Disrupt-net最好ops出现8位数,Disruptor-Java平均在7-8位数作用,看了下这两种不同平台测试时间算法是有区别的java用system.millitime 前后两次相减,而NET使用DateTime.Now前后两次相减,则ops可以达到每秒 9位数,此项目里测试全部使用Stopwatch计算时间。
1亿个消息流水线程模式
测试结果:
每秒消息处理量,运行20次,如下图:
这种模式下BlockingCollection处理能力,太慢了一次处理大概需要150秒,ops每秒只有不到70万,所以不贴图了。
当然这种测试结果因硬件环境而不同!
总的来说,Disruptot的处理能力是惊人的,按照 ,In Memory+Event Source+Disruptor 这种架构风格处理业务,每秒处理600万订单,也是可能的。
这个版本作为技术研究用,代码在 https://github.com/bingyang001/disruptor-net-3.3.0-alpha