前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >disruptor怎么可以这么快

disruptor怎么可以这么快

作者头像
Coder的技术之路
发布2021-05-14 14:11:14
5460
发布2021-05-14 14:11:14
举报
文章被收录于专栏:Coder的技术之路Coder的技术之路

最近同事分享了一个叫做disruptor的并发框架,很感兴趣,觉得很神奇,所以浏览了一下代码,也发现了一些剖析的特好的博客。就想着记录一下,也分享给大家。


Disruptor其实是一个并发组件,能够在无锁的情况下实现队列并发操作。用到了队列,那适用场景基本是生产者-消费者,且消费者有顺序问题这类。

2.0版的结构:生产端,生产者通过PublishPort 接口(生产者屏障),并发的将数据或别的一些虾米东西存入无界环形队列RingBuffer;消费者EventProcessor通过消费屏障拿到数据来并行消费,然后将处理完成的数据交给下一个依赖它结果的消费者,完成处理。

总结一下其极高性能的主要原因,有两个方面:1.无锁并发的实现;2.缓存行填充。

先说下无锁。对于并发问题,觉大多数的解决思路是加锁,这个无可非议。而且,锁的适用,也能够满足大多数并发问题。但是,对于像LMAX公司这样1ns的偏差就可能造成多起跳楼惨案的业务,锁就完全无法胜任的。锁,就意味着慢。当很多线程去抢占资源,获取锁,释放锁,等待锁,是非常耗时的;而且不管是悲观锁,还是乐观锁,都会带来死锁,必须重启服务器的潜在危机。

传说,Disruptor论文中讲述了一个实验测试程序调用了一个函数,该函数会对一个 64位的计数器循环自增5亿次。当单线程无锁时,程序耗时300ms。如果增加一个锁(仍是单线程、没有竞争、仅仅增加锁),程序需要耗时 10000ms,慢了两个数量级。如果增加一个线程,耗时224000ms。使用两个线程对计数器自增5亿次比使用无锁单线程慢1000倍。所以,想要快,唯一的解决办法就是别用锁。

那么生产者怎样去抢占环形队列中的位置--CAS策略:compareAndSet/Swap,这是一个CPU级别的指令,配合volatile原语使用,保证线程间的数据是可见的。java 中的AtomicLong 用的就是这个。这种方式应该是叫做内存屏障什么玩意的(具体咱也不是很清楚,谁要是清楚的话可以给我留言讲一下啊),采用类似乐观锁的方式,去在CPU级别检测资源的值是否被改变,如果改变则抢占失败,说明已经有别的线程抢到了。这比单线程无锁要慢,但是要比加锁快的多。

瞅一眼多生产者下Ringbuffer的next方法,先判断位置是否合法可用,如果赶上了消费者,那就在本地自旋等待,如果可用,就去抢占位置,抢占成功则break,不成功则do while(true)继续抢占下一个。

没有锁,那自然就快了。

再来说一下,缓存行填充。这个就比较高精尖了,按人家的说法,叫做Mechanical Sympathy,翻译一下就是人剑合一。。。。。。

也就是说必须清楚的了解机器的组成和运行原理,才能让代码和机器更好的契合,写出更高效,流弊的程序。这不禁让我这个跨专业入行计算机的泥腿子哭晕一万多次。为毛数学系不开《计算机组成原理》的课。。。

计算机的存储设备,分为,磁盘,内存,cache,这三者距离CPU的距离依次递减,速度依次递增,cache一般都三级,最里面的一般容量最小,速度最快。

而数据,在缓存中存储时,不是已一个单独的项来存储的,而是以缓存行的形式,缓存行构成了缓存,每一个缓存行一般为64字节。

比方说,如果要读取一个8字节long型数据时,不仅仅读取了这个8字节变量,其实,同时还读取了另外七个。

有人想当然的认为这种读取形式会带来不少好处,缓存预读会带来性能的提升;其实不然,甚至正好相反。瞎画个图来表现一下

读取了A的同时,也读取了B。但是A和B是没有密切的联系的,当线程1改变了内存中A的值的时候,A 所在的缓存行也就失效了,这时候,如果有一个不相干的另一个线程2,想要读取B,就必须再到主存里重新读入新A 、B等等64字节的数据。这样势必拖慢处理时间,而且,如果涉及的是两个线程同时对A 和B进行写的时候,就出现线程的写冲突了,虽然,是不同的线程操作不同的数据。

怎么办,那就让一个缓存行里,有且只有一个有效数据,其他位置,都用空数据填充,规避上面所说的数据改变引起的耗时,虽然这样做有点浪费,但也是值得的:

除此之外,Disruptor还有很多值得我们借鉴的地方,比如队列拍马不及的RingBuffer性能,等等,暂且记下,有机会好好用用
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder的技术之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档