0%

JStorm 源码分析 - 高性能队列 DisruptorQueue

在上一篇文章中( JStorm 源码分析 - tuple 在整个拓扑中的流转过程), 我们多次提到 JStorm 使用了 3 个队列来完成 tuple 的缓冲与消费. 因此这些队列的性能会制约 JStorm 的总体的吞吐量.

在日常的工程实践当中, 我们会使用一些 Java 的内置队列来完成这个工作, 比如 ArrayBlockingQueue. 实际上, 如果要追求更高的性能, DisruptorQueue 是一个更好的选择, 它虽然降低了 API 的易用性, 但是在性能上相比于 ArrayBlockingQueue 这类队列提升很大.

Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题 ( 在性能测试中发现竟然与I/O操作处于同样的数量级 ).需要特别指出的是,这里所说的队列是系统内部的内存队列,而不是Kafka这样的分布式队列.

关于 Disruptor 的原理与使用, 网上已经有很多优秀的文章, 可以阅读以下文章来学习:

  1. 美团技术团队 2016-11-18 高性能队列–Disruptor 这篇文章深入浅出,写的很好.
  2. 官方文档 https://lmax-exchange.github.io/disruptor/

Storm/JStorm 就使用 Disruptor 作为队列, 来提高系统的性能. 这里引用一段核心开发成员@longdafeng的采访记录:

封仲淹: (阿里巴巴中间件平台技术部高级技术专家, 花名纪君祥, 阿里巴巴JStorm 核心作者之一)

Disruptor是 LMAX 开源的分布式高性能的队列,这个队列是非常赞的队列,它的性能非常高。我们做过性能测试,它比 BlockingQueue、ConcurrentQueue 要快一个数量级,它的核心原理是对cache有高速的亲和性,在内存有很好的防止 GC 。还有一个更重要的特性,它在锁这块控制的非常细。

像 BlockingQueue、ConcurrentQueue 它们在头尾上有一个锁,这个锁的粒度远远高于Disruptor,Disruptor彻底利用了 CPU 里面的指令级的锁,所以它在锁这块非常的高效,这就是为什么 Disruptor 的性能比 BlockingQueue、ConcurrentQueue 高一个数量级的核心的原理。

我个人的观点,就看你对性能的要求有多高。如果你要达到极致的性能,对延迟要求非常低,而且对高并发要求性能非常高的时候,你肯定要选择 Disruptor 。但是从易用性上来讲,Disruptor使用起来并没有传统的 queue 使用上更方便。你在百万级别并发的时候,我推荐大家使用 Java 的 ConcurrentQueue 跟 BlockingQueue。但是如果你需要更低的延迟的话,我推荐用 Disruptor。

出自 封仲淹:如何优雅地使用Disruptor

总结一下:

  • 性能比 BlockingQueue、ConcurrentQueue 快一个数量级, 原因
    • 无锁设计: 通过CAS实现
    • 对寄存器亲和: 数组
    • 防止GC: 使用数组而非链表
  • 建议:
    • 百万级别并发: 使用 ConcurrentQueue、BlockingQueue
    • 更大的并发以及更低的延迟: 使用 Disruptor