disruptor史上最全之3:8大使用场景详细图解(代码片段)

架构师-尼恩 架构师-尼恩     2022-10-26     303

关键词:

文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 :

  • 免费赠送 :《尼恩Java面试宝典》持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备
  • 免费赠送 经典图书:《Java高并发核心编程(卷1)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
  • 免费赠送 经典图书:《Java高并发核心编程(卷2)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
  • 免费赠送 经典图书:《Netty Zookeeper Redis 高并发实战》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
  • 免费赠送 经典图书:《SpringCloud Nginx高并发核心编程》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
  • 免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取

disruptor 史上最全 系列文章:

作为Java领域最高性能的 队列,没有之一, 大家不光要懂,而是 需要深入骨髓的搞懂

所以,给大家奉上了下面的三篇文章,并且配备了视频进行 详细介绍:

作为Java领域最高性能的 队列,没有之一, 大家不光要懂,而是 需要深入骨髓的搞懂

所以,给大家奉上了下面的三篇文章,并且配备了视频进行 详细介绍:

总的Disruptor 的使用场景

Disruptor 它可以用来作为高性能的有界内存队列, 适用于两大场景:

  • 生产者消费者场景
  • 发布订阅 场景

生产者消费者场景。Disruptor的最常用的场景就是“生产者-消费者”场景,对场景的就是“一个生产者、多个消费者”的场景,并且要求顺序处理。

备注,这里和JCTool 的 MPSC 队列,刚好相反, MPSC 使用于多生产者,单消费者场景

发布订阅 场景:Disruptor也可以认为是观察者模式的一种实现, 实现发布订阅模式。

当前业界开源组件使用Disruptor的包括Log4j2、Apache Storm等,

Disruptor 使用细分场景

Disruptor是一个优秀的并发框架,可以使用在多个生产者单消费者场景

  • 单生产者多消费者场景
  • 多生产者单消费者场景
  • 单生产者多消费者场景
  • 多个消费者串行消费场景
  • 菱形方式执行场景
  • 链式并行执行场景
  • 多组消费者相互隔离场景
  • 多组消费者航道执行模式

单生产者多消费者并行场景

在并发系统中提高性能最好的方式之一就是单一写者原则,对Disruptor也是适用的。

如果在生产者单消费者 需求中仅仅有一个事件生产者,那么可以设置为单一生产者模式来提高系统的性能。

ProducerType 的类型

ProducerType 定义了生产者的类型, 两类

在这种场景下,ProducerType 的类型的 SINGLE

单生产者多消费者并行场景的参考代码

参考的代码如下:

执行结果:

以上用例的具体减少,请参见 尼恩《100wqps 日志平台实操,视频》

多生产者单消费者场景

该场景较为简单,就是多个生产者,单个消费者

其实,消费者也可以是多个

ProducerType 的类型

ProducerType 定义了生产者的类型, 两类

在这种场景下,ProducerType 的类型的 MULTI

多生产者场景的要点

在代码编写维度,多生产者单消费者场景的要点如下:

  • 创建Disruptor 的时候,将ProducerType.SINGLE改为ProducerType.MULTI,

  • 编写多线程生产者的相关代码即可。

多生产者场景的参考代码

参考的代码如下:

运行的结果如下

以上用例的具体减少,请参见 尼恩《100wqps 日志平台实操,视频》

单生产者多消费者竞争场景

该场景中,生产者为一个,消费者为多个,多个消费者之间, 存在着竞争关系,

也就是说,对于同一个事件event ,多个消费者 不重复消费

disruptor如何设置多个竞争消费者?

首先,得了解一下,disruptor框架的两个设置消费者的方法

大概有两点:

  • 消费者需要 实现 WorkHandler 接口,而不是 EventHandler 接口
  • 使用 handleEventsWithWorkerPool 设置 disruptor的 消费者,而不是 handleEventsWith 方法

在disruptor框架调用start方法之前,有两个方法设置消费者:

  • disruptor.handleEventsWith(EventHandler … handlers),将多个EventHandler的实现类传入方法,封装成一个EventHandlerGroup,实现多消费者消费。
  • disruptor.handleEventsWithWorkerPool(WorkHandler … handlers),将多个WorkHandler的实现类传入方法,封装成一个EventHandlerGroup实现多消费者消费。

那么,以上的Disruptor类的handleEventsWith,handleEventsWithWorkerPool方法的联系及区别是什么呢?
相同的在于:

两者共同点都是,将多个消费者封装到一起,供框架消费事件。

第一个不同点在于:

对于某一条事件 event,

handleEventsWith 方法返回的EventHandlerGroup,Group中的每个消费者都会对 event 进行消费,各个消费者之间不存在竞争。

handleEventsWithWorkerPool方法返回的EventHandlerGroup,Group的消费者对于同一条事件 event 不重复消费;也就是,如果c0消费了事件m,则c1不再消费事件m。

另外一个不同:

在设置消费者的时候,Disruptor类的handleEventsWith,handleEventsWithWorkerPool方法所传入的形参不同。对于独立消费的消费者,应当实现EventHandler接口。对于不重复消费的消费者,应当实现WorkHandler接口。

因此,根据消费者集合是否独立消费事件,可以对不同的接口进行实现。也可以对两种接口同时实现,具体消费流程由disruptor的方法调用决定。

演示代码如下:

执行结果

以上用例的具体减少,请参见 尼恩《100wqps 日志平台实操,视频》

多个消费者串行消费场景

在 多个消费者串行消费场景中,多个消费者,可以按照次序,消费消息。

比如:一个用户注册的Event,需要有一个Handler来存储信息,一个Hanlder来发邮件等等。

多个消费者串行消费场景案例

执行结果

菱形方式执行场景

场景特点

先并发,后串行

菱形方式执行场景案例

执行结果

链式并行执行场景

场景特点

多组消费者形成 并行链,特点是:

  • 链内 串行

  • 链间 并行

场景案例

执行结果

多组消费者相互隔离场景

场景特点

多组消费者 相互隔离,特点是:

  • 组内 相互竞争

  • 组间 相互隔离

场景案例

执行结果

多组消费者航道执行模式

场景特点

多组消费者形成 并行链,特点是:

  • 组内 相互竞争

  • 组之间串行依次执行

场景案例

组之间串行依次执行,组内有多个实例竞争执行

执行效果

六边形执行顺序

这是一种比较复杂的场景

场景特点

单边内部是有序的

边和边之间是并行的

参考代码

   @org.junit.Test
    public void testHexagonConsumerDisruptorWithMethodRef() throws InterruptedException 
        // 消费者线程池
        Executor executor = Executors.newCachedThreadPool();
        // 环形队列大小,2的指数
        int bufferSize = 1024;
        // 构造  分裂者 (事件分发者)
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize,
                executor,
                ProducerType.SINGLE,  //多个生产者
                new YieldingWaitStrategy());

        EventHandler consumer1 = new LongEventHandlerWithName("consumer 1");
        EventHandler consumer2 = new LongEventHandlerWithName("consumer 2");
        EventHandler consumer3 = new LongEventHandlerWithName("consumer 3");
        EventHandler consumer4 = new LongEventHandlerWithName("consumer 4");
        EventHandler consumer5 = new LongEventHandlerWithName("consumer 5");
        // 连接 消费者 处理器
        // 可以使用lambda来注册一个EventHandler

        disruptor.handleEventsWith(consumer1,consumer2);
        disruptor.after(consumer1).handleEventsWith(consumer3);
        disruptor.after(consumer2).handleEventsWith(consumer4);
        disruptor.after(consumer3,consumer4).handleEventsWith(consumer5);
        // 开启 分裂者(事件分发)
        disruptor.start();
        // 获取环形队列,用于生产 事件
        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
        //1生产者,并发生产数据
        LongEventProducerWithTranslator producer = new LongEventProducerWithTranslator(ringBuffer);
        Thread thread = new Thread() 
            @Override
            public void run() 
                for (long i = 0; true; i++) 
                    producer.onData(i);
                    ThreadUtil.sleepSeconds(1);
                
            
        ;
        thread.start();
        ThreadUtil.sleepSeconds(5);
    

执行结果

参考文献

https://blog.csdn.net/hxg117/article/details/78064632

http://openjdk.java.net/projects/jdk8/features
http://beautynbits.blogspot.co.uk/2012/11/the-end-for-false-sharing-in-java.html
http://openjdk.java.net/jeps/142
http://mechanical-sympathy.blogspot.co.uk/2011/08/false-sharing-java-7.html
http://stackoverflow.com/questions/19892322/when-will-jvm-use-intrinsics
https://blogs.oracle.com/dave/entry/java_contented_annotation_to_help

https://www.jianshu.com/p/b38ffa33d64d

https://blog.csdn.net/MrYushiwen/article/details/123171635

https://blog.csdn.net/everyok/article/details/88889057

disruptor(史上最全之1):伪共享原理&性能对比实战(代码片段)

...,不断更新、持续迭代具体详情,请点击此链接disruptor史上最全系列文章:作为Java领域最高性能的队列, 查看详情

disruptor(史上最全之1):伪共享原理&性能对比实战(代码片段)

...,不断更新、持续迭代具体详情,请点击此链接disruptor史上最全系列文章:作为Java领域最高性能的队列, 查看详情

nginx详细参数配置(史上最全)

前言Nginx配置参数中文详细说明:1、定义Nginx运行的用户和用户组userwwwwww;2、nginx进程数,建议设置为等于CPU总核心数.worker_processes8;3、全局错误日志定义类型,[debug|info|notice|warn|error|crit]error_log/var/log/nginx/error.loginfo;4、进程文件... 查看详情

史上最全mysql总结mysql超详细笔记(代码片段)

【史上最全MYSQL总结】MySQL超详细笔记      本文主要介绍了mysql是个啥、他的分类、SQL命令,MySQL的安装注意事项、分类以及在MySQL中常用的命令,包括:数据查询(基本查询、排序查询、条件查询、时间查询、... 查看详情

史上最全云原生全景图解读攻略

带你了解云原生技术图谱​如果你研究过云原生应用程序和相关技术,大概率你遇到过CNCF的云原生全景图。这张全景图技术之多、规模之大无疑会让人感到震惊,那么我们该如何去理解这张图呢?如果把它拆开来ÿ... 查看详情

史上最全云原生全景图解读攻略

带你了解云原生技术图谱​如果你研究过云原生应用程序和相关技术,大概率你遇到过CNCF的云原生全景图。这张全景图技术之多、规模之大无疑会让人感到震惊,那么我们该如何去理解这张图呢?如果把它拆开来ÿ... 查看详情

jmeter之json提取器详解(史上最全)(代码片段)

参考资料:https://www.bbsmax.com/A/D854lmBw5E/Jsonpath在线测试:http://jsonpath.com/实际工作中用到的一些场景:提取某个特定的值提取多个值按条件取值阵列取值(返回所有元素的列表/数组)提取多个值Jsonpath提取器需要另外安装下载plugi... 查看详情

深入java微服务之网关系列3:springcloudalibabagateway详解(史上最全)(代码片段)

九、服务网关:Gateway9.1、网关简介    大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微... 查看详情

nginx详细参数配置(史上最全)

前言Nginx配置参数中文详细说明:1、定义Nginx运行的用户和用户组userwwwwww;2、nginx进程数,建议设置为等于CPU总核心数.worker_processes8;3、全局错误日志定义类型,[debug|info|notice|warn|error|crit]error_log/var/log/nginx/error.loginfo;4、进程文件... 查看详情

队列之王:disruptor原理架构源码一文穿透(代码片段)

文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+... 查看详情

史上最全的python的web开发和网络编程附属详细解释+案例(代码片段)

文章目录1.IP地址2.端口2.1端口介绍2.2端口号介绍3.TCP3.1为什么要用TCP?3.2TCP和UDP的解释3.3TCP步骤和特点4.socket(套接字)5.TCP网络应用程序开发流程(重要)5.1刚安装ubuntu20遇到的问题5.2TCP两个程序开发过程5.3TCP客户端开发程序5.3TCP... 查看详情

史上elasticsearch最全详细使用教程

‍‍点击上方关注“终端研发部”设为“星标”,和你一起掌握更多数据库知识来源:r6a.cn/cyJw本文介绍了ElasticSearch的必备知识:从入门、索引管理到映射详解。一、快速入门1. 查看集群的健康状况http://localhost:9200/_... 查看详情

史上最全最详细jndi数据源配置说明(代码片段)

史上最全最详细JNDI数据源配置说明转载:https://blog.csdn.net/zhanglf02/article/details/767267022017年08月05日17:12:08阅读数:4466环境:tomcat6.0+Maven要使用数据源就要知道数据源的由来:在java开发使用jdbc都要经历这四步①加载数据库驱动程... 查看详情

史上最全云原生全景图解读攻略

带你了解云原生技术图谱​如果你研究过云原生应用程序和相关技术,大概率你遇到过CNCF的云原生全景图。这张全景图技术之多、规模之大无疑会让人感到震惊,那么我们该如何去理解这张图呢?如果把它拆开来ÿ... 查看详情

史上最全wireshark使用教程,8万字整理总结,建议先收藏再耐心研读

 目录第 1 章 介绍...11.1. 什么是Wireshark.11.1.1. 主要应用...11.1.2. 特性...11.1.3. 捕捉多种网络接口...21.1.4. 支持多种其它程序捕捉的文件...21.1.5. 支持多格式输出...21.1.6. 对多种协议解码提供支持...21.1.7. 开源软件...21.1.8. Wire... 查看详情

史上最全wireshark使用教程,8万字整理总结,建议先收藏再耐心研读

 目录第 1 章 介绍...11.1. 什么是Wireshark.11.1.1. 主要应用...11.1.2. 特性...11.1.3. 捕捉多种网络接口...21.1.4. 支持多种其它程序捕捉的文件...21.1.5. 支持多格式输出...21.1.6. 对多种协议解码提供支持...21.1.7. 开源软件...21.1.8. Wire... 查看详情

史上最全的并发编程学习目录

目录一:线程基础知识1.并发编程的基本概念2.线程的基本操作3.线程之间的通信wait和notify4.join和yield以及sleep详解5.synchronized关键字讲解6.volatile原理7.线程组8.线程优先级9.守护线程10.ThreadLocal二:JDK并发包1.jdk并发工具类2.jdk并发... 查看详情

时间轮(史上最全)(代码片段)

缓存之王Caffeine中,涉及到100w级、1000W级、甚至亿级元素的过期问题,如何进行高性能的定时调度,是一个难题。注:本文从对海量调度任务场景中,高性能的时间轮算法,做了一个系统化、由浅入深的穿... 查看详情