文档章节

高性能队列disruptor浅析

loubobooo
 loubobooo
发布于 02/26 15:40
字数 946
阅读 63
收藏 0

最近翻看技术文章,发现一个叫做disruptor的高性能内存队列占据了头版头条,好奇其高性能的秘密,于是对该框架进行了一些简单的研究。disruptor并非新出,而是从2013年到现在经历了3个大版本的迭代。本文有如下几个部分:

  1. disruptor如何使用?
  2. disruptor高性能的秘密?

如何使用

核心概念:

  1. EventFactory:用于生成一个事件提供消费者消费
  2. EventHandler:消费者处理器
  3. 事件和生产者:无内部接口,可以自己封装实体对象和RingBuffer
  4. RingBuffer:核心数据结构,可以理解为环形缓冲,disruptor高性能秘密
  5. WaitStrategy:消费者阻塞时候的等待策略:SleepingWaitStrategy,BlockingWaitStrategy,BusySpinWaitStrategy,YieldingWaitStrategy
  6. Disruptor:disruptor框架入口,进行相关配置

事件和工厂

public static class LogEvent {
    String content;
    public void setContent(String content) {
        this.content = content;
    }
}
public static class LogEventFactory implements EventFactory<LogEvent> {
    @Override
    public LogEvent newInstance() {
        return new LogEvent();
    }
}

消费者

public static class LogEventHandler implements EventHandler<LogEvent> {
    @Override
    public void onEvent(LogEvent event, long sequence, boolean endOfBatch) throws Exception {
        System.out.println(Thread.currentThread().getName() + ",seq=" + sequence + ",event=" + event.content);
    }
}

生产者

public static class LogEventProducer {
    private final RingBuffer<LogEvent> ringBuffer;
    public LogEventProducer(RingBuffer<LogEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }
    public void onData(String content) {
        long seq = ringBuffer.next();
        try {
            LogEvent logEvent = ringBuffer.get(seq);
            logEvent.setContent(content);
        } finally {
            ringBuffer.publish(seq);
        }
    }
}
public static void main(String[] args) {
    LogEventFactory eventFactory = new LogEventFactory();
		
    // 缓冲区大小
    int bufferSize = 16;
    // ProducerType有single和multi之分,分别对应不同的RingBuffer实现,性能不同
    // WaitStrategy对应消费者阻塞时的处理策略
    Disruptor<LogEvent> disruptor = new Disruptor<>(eventFactory, bufferSize,
        (ThreadFactory)Thread::new,
        ProducerType.MULTI,
        new BlockingWaitStrategy());
			
    //挂载消费者,可以有多个消费者,并可以通过Group自由链接组合关系
    disruptor.handleEventsWith(new LogEventHandler());
    disruptor.start();
		
    RingBuffer<LogEvent> ringBuffer = disruptor.getRingBuffer();
    LogEventProducer producer = new LogEventProducer(ringBuffer);
    for (int i = 0; i < 20; i++) {
        producer.onData("this is a log event i=" + i);
    }
}

高性能的秘密

如下是高性能的秘密,我个人理解和简述:

lock-free

ArrayBlockingQueue使用lock实现并发控制,无论get或者put,都是将final ReentrantLock lock;进行上锁,毋庸置疑当c/p大量并发时会有性能损失。

相比,disruptor通过’分离竞争点’解决大量cp并发问题。即当:

1p(product)-1c(consume):无特殊
1p(product)-多c(consume):每个消费者使用独立的seq,即分离竞争点。disruptor不会清理数据,循环覆盖。
多p(product)-多c(consume):多p之间采用cas操作。内部实现AtomicLong
多p(product)-1c(consume):与3一样
这种分离竞争点技术思想,也用于LongAdder以及ConcurrentHashMap

伪共享和缓存行填充

L1cache是计算机体系结构中重要组成部分,我们都知道L1Cache的作用:缓存memory热点数据,以加快cpu访问。在多核时代,由于不同cpu的缓存中拥有相同内存区域的不同副本,因此,L1Cache之间的同步是有其成本的,这需要使用内存控制器以及MESI协议。缓存以行作为最小加载单元(64byte=8个long),如上图,当队列首位指针(disruptor使用seq),被加载到相同的缓存行的时候,c1处理生产,c2处理消费,而首位指针其实是独立的但却进行了共享(伪共享),导致L1Cache的缓存行刷新。

解决办法很明显,h,t分别放到不同的缓存行上。查看源码时有如下代码:

性能优越性

给一个官方disruptor与ArrayBlockingQueue的性能测试结果:

参考链接

http://ifeve.com/disruptor/
http://www.cnblogs.com/cyfonly/p/5800758.html
https://github.com/LMAX-Exchange/disruptor

© 著作权归作者所有

loubobooo

loubobooo

粉丝 14
博文 73
码字总数 83251
作品 0
杭州
程序员
私信 提问
Disruptor学习之路(一)

Disruptor是什么? Disruptor是一个高性能的异步处理框架,或者可以认为是线程间通信的高效低延时的内存消息组件,它最大特点是高性能,其LMAX架构可以获得每秒6百万订单,用1微秒的延迟获得...

ChyiHuang
2018/12/17
176
0
高性能无锁队列 Disruptor 初体验

原文地址: haifeiWu和他朋友们的博客 博客地址:www.hchstudio.cn 欢迎转载,转载请注明作者及出处,谢谢! 最近一直在研究队列的一些问题,今天楼主要分享一个高性能的队列 Disruptor 。 ...

haifeiWu
2018/08/16
0
0
(转)disruptor - Concurrent Programming Framework...

disruptor发布了Java的2.0版本(.Net版本见这里),disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式实现,或者事件-监听模式的实...

猴子
2011/10/23
901
0
高性能高并发队列-Disruptor

Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒...

满小茂
2016/12/09
3K
0
高性能队列 Disruptor

偶然中看到一篇 关于disruptor的分析,高性能低延迟的特性吸引了我。 disruptor java实现的线程间通信的高性能低延迟消息组件,也就是消息队列,相比于BlockingQueue 最大的特点在于无锁的机...

ovirtKg
2016/12/15
89
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS盒子模型

一、什么叫框模型 页面元素皆为框(盒子) 定义了元素框处理元素内容,内边距,外边距以及边框的计算方式 二、外边距 围绕在元素边框外的空白距离(元素与元素之间的距离) 语法:margin,定...

wytao1995
今天
4
0
Replugin借助“UI进程”来快速释放Dex

public static boolean preload(PluginInfo pi) { if (pi == null) { return false; } // 借助“UI进程”来快速释放Dex(见PluginFastInstallProviderProxy的说明) return PluginFastInsta......

Gemini-Lin
今天
4
0
Hibernate 5 的模块/包(modules/artifacts)

Hibernate 的功能被拆分成一系列的模块/包(modules/artifacts),其目的是为了对依赖进行独立(模块化)。 模块名称 说明 hibernate-core 这个是 Hibernate 的主要(main (core))模块。定义...

honeymoose
今天
4
0
精华帖

第一章 jQuery简介 jQuery是一个JavaScript库 jQuery具备简洁的语法和跨平台的兼容性 简化了JavaScript的操作。 在页面中引入jQuery jQuery是一个JavaScript脚本库,不需要特别的安装,只需要...

流川偑
今天
7
0
语音对话英语翻译在线翻译成中文哪个方法好用

想要进行将中文翻译成英文,或者将英文翻译成中文的操作,其实有一个非常简单的工具就能够帮助完成将语音进行翻译转换的软件。 在应用市场或者百度手机助手等各大应用渠道里面就能够找到一款...

401恶户
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部