# What?
java一个内存blockingQueue库
# jvm不是有现成的blockingQueue了么?Disruptor有何不同?
https://www.bittiger.io/classpage/QHkP5QobvhNWGZv9f
这个讲的最好
https://time.geekbang.org/column/article/79871
https://time.geekbang.org/column/article/98134
Disruptor做了很多优化,因此更加cache friendly(减少访存、增加cache利用率)。优化的手段包括: 内存填充解false sharing;无锁减少context switch等。
值得一提的是,无锁不只是使用cas,还包括很多trick:允许多个consumer互相隔离(无共享的思想)、允许多个producer申请不同的资源从而减少竞争(即使一个producer阻塞住了,其他producer可以继续produce、生产到别的slot里)、建议用法为单producer多consumer模式(避免多producer间可能cas冲突)。
# 如何实现?源码分析
从源码的角度讲,publishEvents其实就是先cas申请空间,申请到了再设置值.
怎么保证消费者不会消费到刚申请、还没设置值的slot?
设置完成之后再统一改标识,统一commit。即:
```
private void translateAndPublishBatch(
final EventTranslator<E>[] translators, int batchStartsAt,
final int batchSize, final long finalSequence)
{
final long initialSequence = finalSequence - (batchSize - 1);
try
{
long sequence = initialSequence;
final int batchEndsAt = batchStartsAt + batchSize;
for (int i = batchStartsAt; i < batchEndsAt; i++)
{
final EventTranslator<E> translator = translators[i];
translator.translateTo(get(sequence), sequence++);
}
}
finally
{
sequencer.publish(initialSequence, finalSequence);
}
}
```
# 所以消费者会被生产者block?
等待策略有多种,默认(推荐,为了更低的latency)是忙等。
[源码解析](https://juejin.im/entry/5baafcc86fb9a05cd77748e6)有写两种消费模式,单线程/多线程。
都是顺序消费sequence,单线程是批量处理,多线程是多线程cas申请一个slot,申请到了再消费
# 搞懂了原理之后,思考一下Disruptor的应用场景是?
1. low latency要求很高、可以牺牲cpu去换latency的场景,如高频交易(看bittiger的讲解时没有理解,为什么高频交易要用java?)
2. 不管是解false sharing还是无锁减少context switch,本质上优化的结果是更加cache friendly(减少访存、增加cache利用率)。
那么对于要访外的场景,这点优化都是零头?而且consumer访外会导致ring buffer满了、producer忙等,白优化了。
3. 用了很多忙等,吃cpu获取更低的latency(而这latency相较于访外是零头)。看起来并不适合互联网海量吞吐、每个请求都要数次磁盘io或者网络io的场景?
网友评论