Disruptor引起的思考

来源:互联网 发布:知网数据库论文检测 编辑:程序博客网 时间:2024/05/01 16:31

    多任务,并发控制的代码,我在项目中使用的次数不是太多,有过4、5次经验。还记得第一次用的线程池的时候,还需要自己维护入池,出池,线程状态,由于经验不足,经常宕机。随着后来不断改进,自己越来越对多线程控制有感觉了。

    我对自己对多线程并发-任务调度的理解层次分层了3个阶段:

    1)任务完全独立,没有调度设计:利用数据库表唯一索引作为任务控制权抢占的解决方案。没有设计任务调度程序。每个任务都是独立的。每个线程将被分配一个独立的任务处理逻辑。任务处理逻辑都是以获取记录处理权控制开始,然后处理记录,输出结果。会有一个守护线程,扫描任务运行情况,对运行异常的任务数据记录,进行过程数据擦除,还原初始状态。

    2)任务建立简单依赖关系,有简单调度控制:形成这种设计思想,是由于学习了2、3个月Scala Akka(基于Actor模型)结构,对其中的不变数据对象,不共享数据,不引入竞争机制,甚为赞同。所以自己的主控程序逻辑其实就是生成任务数据,并按任务消费者的优先级,逐级进行任务派发给任务记录的副本。根据每个消费者相关设定,在任务处理失败时进行重算还是直接放弃。这个阶段的任务派发还是沿用了第一阶段的思想,就是每个级别的任务消费处理逻辑都是完全独立的。

    但是Akka的设计核心其实已经再利用协程概念了,就是尽量不让线程进行过多的无谓切换。线程之间是有联系的。当一个线程停止运行时,能够准确的通知一个可以运行的线程,这个可以运行的线程他所需要的资源已经准备好了,而不是随机启动的。

    所以可以说,第二阶段我的设计用了Akka的形,但是核心还是第一阶段老调调。

    3)任务建立关联关系,设计真正的调度逻辑,这是我今后的设计方向,需要参考Disruptor项目

    这个理念的产生,是我发现自己前面两个阶段设计的并发结构过于简单,没有太多的应用控制。解决方案有点像一个工具API。其实在JDK5以后,Java在并发方面API下了很大的功夫,提供了很多新的设计思想。允许我们进行更细节的线程状态控制。可能是担心自己玩的不好,不太敢使用太多的新API。

    这几天看了很长时间的LMAX开源的Disruptor项目,它并获得2011 Duke's 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作。LMAX团队也研究过Scala的Akka项目,LMAX团队在设计并测试了Actor模型原型后,发现处理器会花费很多时间在管理队列上,而不是去做真正应用逻辑,队列访问成为瓶颈。为此,他们经过仔细分析和测量后,定位到了问题所在,通过从操作系统调度层面减少锁的使用,和从处理器内核层面减少访问高速缓存的争用,推出了Disruptor

    通过了解Disruptor的设计,给我在并发设计上面打开了新的一扇窗:

    1、原来一直以为算法才是关键,其实计算机本身接口也是一个影响的关键点,你需要了解Memory Barrier,CPU Cache Line以及 如何Padding避免CPU False Sharing。也就是Mechanical Sympathy:Hardware and software working together in harmony。

    2、任务调度和任务处理可以解耦,靠存储数据解耦,这个用烂的解耦方法,可以我就是偏偏忘记加入到我设计。Disruptor用一个RingBuffer数据对象,在JVM中做到了一个类似JMS的消息传递机制。这个真的令人叹服。

    3、消息处理可以形成步骤责任链。也就是说你可以把消息处理逻辑进一步细化,如何调度控制可以完全交个Disruptor了。


   Akka的Actor也有消息传递机制,每个Actor是子Actor的调度控制者,父Actor是Sender,子Actor是Receiver。同级Actor之间的交互需要通过父Actor调度完成。父actor将要处理的任务分发到子Actor实例对象中。每个子Actor处理的任务是不一样的。


   Disruptor生产者和消费者的事件传递靠broadcast post来完成。每个eventhandler都会收到完整的生产者事件。其实如果想做到事件只被处理一次,也很简单,也就是让Event内置一个

Atomic对象即可。哪个消费者可以修改atomic对象,谁就处理这个Event。不要担心EventHandler执行一次onEvent,就会导致所在线程切换。在事件获取的时候,Disruptor不是一次只拿一个Event,而是会拿很多个,是一个批量的处理过程(EventHandler都会被添加到BatchEventProcessor)。可以看得出来Disruptor的设计理念是尽可能让线程切换少,让线程在运行的时候,尽可能准备消费者多次运行数据。

0 0
原创粉丝点击