Disruptor

Disruptor技术调研之配置参数一览

旧城冷巷雨未停 提交于 2019-11-30 10:59:15
1、单生产者和多生产者 One of the best ways to improve performance in concurrect systems is to ahere to the Single Writer Princple, this applies to the Disruptor. If you are in the situation where there will only ever be a single thread producing events into the Disruptor, then you can take advantage of this to gain additional performance. 上述的描述大致的意思是在多并发的系统中,如果选择基于单生产者的Disruptor,能够获得比多生产者更好的性能。 2、可选择的等待策略 1)Disruptor默认的等待策略是BlockingWaitStrategy。内部是使用lock和condition来进行线程间的协作的。相对于其他的策略是最慢的但对cpu的使用是最保守的,也是所有选项中一致性行为最高的。 2)和BlockingWaitStrategy一样,SleepingWaitStrategy尝试保守的使用cpu,通过使用busy wait loop

高性能高并发队列-Disruptor

依然范特西╮ 提交于 2019-11-30 10:59:00
Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了业界关注。2011年,企业应用软件专家Martin Fowler专门撰写长文介绍。同年它还获得了Oracle官方的Duke大奖。 Java内置队列 介绍Disruptor之前,我们先来看一看常用的线程安全的内置队列有什么问题。Java的内置队列如下表所示。 队列 有界性 锁 数据结构 ArrayBlockingQueue bounded 加锁 arraylist LinkedBlockingQueue optionally-bounded 加锁 linkedlist ConcurrentLinkedQueue unbounded 无锁 linkedlist LinkedTransferQueue unbounded 无锁 linkedlist PriorityBlockingQueue unbounded 加锁 heap DelayQueue unbounded 加锁 heap 队列的底层一般分成三种:数组、链表和堆。其中,堆一般情况下是为了实现带有优先级特性的队列,暂且不考虑。 我们就从数组和链表两种数据结构来看

深入浅出计算机组成原理:理解Disruptor(下)-不需要换挡和踩刹⻋的CPU,有多快?(第55讲)

眉间皱痕 提交于 2019-11-29 17:31:08
一、引子 上一讲,我们学习了一个精妙的想法,Disruptor通过缓存行填充,来利用好CPU的高速缓存。不知道你做完课后思考题之后,有没有体会到高速缓存在实践中带来的速度提升呢? 不过,利用CPU高速缓存,只是Disruptor“快”的一个因素,那今天我们就来看一看Disruptor快的另一个因素,也就是“无锁”,而尽可能发挥CPU本身的高速处理性能。 二、缓慢的锁 Disruptor作为一个高性能的生产者-消费者队列系统,一个核心的设计就是通过RingBuffer实现一个无锁队列。 上一讲里我们讲过,Java里面的基础库里,就有像LinkedBlockingQueue这样的队列库。但是,这个队列库比起Disruptor利用的RingBuffer要慢上很多。慢的第益个原因我们说过, 因为链表的数据在内存里面的布局对于高速缓存并不友好,而RingBuffer所使用的数组则不然。 LinkedBlockingQueue慢,有另外一个重要的因素,那就是它对于锁的依赖。在生产者-消费者模式里,我们可能有多个消费者,同样也可能有多个生产者。多个生产者都要往队列的尾指针里面添加新的任务, 就会产生多个线程的竞争。于是,在做这个事情的时候,生产者就需要拿到对于队列尾部的锁。同样地,在多个消费者去消费队列头的时候,也就产生竞争。同样消费者也要拿到锁。 那只有意个生产者,或者一个消费者

Disruptor、Kafka、Netty整合之路

二次信任 提交于 2019-11-29 16:45:36
NETTY应用网关 整个网关的核心是一个netty server,各个应用程序(包括web server,手机app等)连到这个netty server上请求数据;关于数据来源,需要监听多个kafka topic(而且这里的topic是可变的,也就是说需要kafka consumer的动态开始和停止),之后需要把所有这些topic的数据整合在一起,通过channel发送给客户端应用程序。 数据流图 源码 下面把大部分的代码贴出来,有需要的同学可以参考。会对关键的技术点进行说明,偏业务部分大家自行忽略吧。 main函数 启动disruptor;监听一个固定的topic,把获取到的msg,交给ConsumerProcessorGroup来完成kafka consumer的创建和停止。 public static void main(String[] args) { DisruptorHelper.getInstance().start(); Properties props = ConsumerProps.getConsumerProps(); KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props); consumer.subscribe(Arrays.asList(

并发框架Disruptor几个Demo

纵然是瞬间 提交于 2019-11-29 16:45:23
扫盲: 要想了解Disruptor框架必需多花点时间研究下它的工作原理,不然代码是没法撸的!!! 关于Disruptor的详细资料及原理请细看!!! http://ifeve.com/disruptor/ Disruptor版本: 3.2.1 名词解释 消费者==事件处理器 一、现在你必须明白以下问题: 1、你必须明白Ringbuffer是什么,它的数据结构是怎么样的,有什么约定,为什么高效,它的职责是什么。 2、ConsumerBarrier (ifeve网上的译文版本比较早,这个类在2.0.0之后就一直被改名,3.2.1的版本中它是SequenceBarrier)它的职责是什么。 Disruptor框架在2.0版本之后不再采用生产者、消费者模型来编写API,而是使用事件模型,其实只是接口设计、类名和概念上的变化,内部原理其实还是一样的。 DEMO 一、使用原生API创建一个简单的生产者和消费者 Java代码 //DEMO中使用的 消息全假定是一条交易 public class TradeTransaction { private String id; //交易ID private double price; //交易金额 public TradeTransaction() { } public TradeTransaction(String id, double price)

Disruptor (5)

瘦欲@ 提交于 2019-11-29 08:53:24
handleEventsWith & handleEventsWithWorkerPool 在disruptor框架调用start方法之前,需要将消息的消费者指定给disruptor框架。 disruptor. handleEventsWith (EventHandler... handlers),将多个 EventHandler 的实现类传入方法,封装成一个 EventHandlerGroup 。 disruptor. handleEventsWithWorkerPool (WorkHandler... handlers),将多个 WorkHandler 的实现类传入方法,封装成一个 EventHandlerGroup 。 不同点 handleEventsWith方法的 EventHandlerGroup 中的每个消费者都会对同一条消息m进行消费,各个消费者之间不存在竞争。 handleEventsWithWorkerPool方法返回的 EventHandlerGroup ,Group的消费者对于同一条消息m不重复消费;如果c0消费了消息m,则c1不再消费消息m。 对于独立消费的消费者,应当实现EventHandler接口。对于不重复消费的消费者,应当实现WorkHandler接口。 从代码层面而言, 有不同的具体实现来支持不同的模式 ConsumerInfo

Disruptor (5)

◇◆丶佛笑我妖孽 提交于 2019-11-29 08:52:56
handleEventsWith & handleEventsWithWorkerPool 在disruptor框架调用start方法之前,需要将消息的消费者指定给disruptor框架。 disruptor. handleEventsWith (EventHandler... handlers),将多个 EventHandler 的实现类传入方法,封装成一个 EventHandlerGroup 。 disruptor. handleEventsWithWorkerPool (WorkHandler... handlers),将多个 WorkHandler 的实现类传入方法,封装成一个 EventHandlerGroup 。 不同点 handleEventsWith方法的 EventHandlerGroup 中的每个消费者都会对同一条消息m进行消费,各个消费者之间不存在竞争。 handleEventsWithWorkerPool方法返回的 EventHandlerGroup ,Group的消费者对于同一条消息m不重复消费;如果c0消费了消息m,则c1不再消费消息m。 对于独立消费的消费者,应当实现EventHandler接口。对于不重复消费的消费者,应当实现WorkHandler接口。 从代码层面而言, 有不同的具体实现来支持不同的模式 ConsumerInfo

程序员如何培养解决复杂问题的能力?

怎甘沉沦 提交于 2019-11-29 06:14:50
今天在上网时候,突然看到了这篇文章,感觉非常的适合现在的自己去思考下,可能也适用在座的读者。程序员不仅仅是敲代码,更是一个复合能力的结合体,也不仅仅停留在技术和代码阶段。你想要成长就得重新审视下“程序员”,看看自己的基础是否牢固,万丈高楼平地起,说的就是这个意思,聊天时候很多人说“程序员只要懂得多,不需要那么深的。”其实这句话是错的,比如说,disruptor底层是个什么结构?为什么选这种结构?解决了什么问题?什么原理呢?你都知道吗?只知其然,不知其所以然是不行的!看看自己现在项目中你能发现什么问题,或者说能预料到什么问题,有什么解决方案,最优方案是如何定下来的?这一系列的问题都是进阶“程序员”所必备的,死写代码是不行的。(非原作者所述) 程序员大致可以分为三类:码农、工程师、高级工程师 Level 1 - 码农 能做事,但缺乏思考,Coding只是体力活。 Level 2 - 工程师 不盲目,懂得思考与进步。 Level 3 - 高级工程师 不止有足够的思考,还具备 解决复杂问题的能力 。 从码农到工程师并不难,只要懂得不盲从、主动思考、学习、改善就可以很容易进入工程师的行列,但是大多数就止步于工程师了,因为要从工程师成长到高级工程师,需要 解决复杂问题的能力 。 什么是复杂问题 首先明确一点: 解决问题 ≠ 解决复杂问题 问题 = problem 复杂问题 = (

Disruptor 框架的简单实践

淺唱寂寞╮ 提交于 2019-11-28 22:47:52
Disruptor 框架的简单实践 基础知识 架构图 核心概念 简单实践 https://github.com/LMAX-Exchange/disruptor/wiki/Introduction https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started http://lmax-exchange.github.io/disruptor/files/Disruptor-1.0.pdf 基础知识 理解Disruptor是什么的最好方法是将它与目前很好理解和非常相似的东西进行比较。 在Disruptor的情况下,这将是Java的 BlockingQueue 。与队列一样,Disruptor的目的是在同一进程内的线程之间移动数据(例如消息或事件)。 但是,Disruptor提供了一些将其与队列区分开来的关键功能。他们是: 具有消费者依赖关系图的消费者多播事件。 为事件预先分配内存。 可选择无锁。 架构图 核心概念 Ring Buffer Sequence Wait Strategy EventHandler 简单实践 任务类 package morning . cat ; import lombok . Data ; import lombok . ToString ; /** * 任务模型 */ @Data

Disruptor (3) - 与ArrayBlockingQueue的性能比对

拈花ヽ惹草 提交于 2019-11-28 21:59:22
本次代码测试基于相同的 容量、生产者线程、单个生产者生产量、单个消费线程。 测试结果: 经测试证明: 在容量达到阀值时, Disruptor的性能更突出 RingBuffer 的大小 与 消费者的消费速度 都直接影响到整个耗时。 测试入口 package com.lmax.disruptor.noob; import java.time.Instant; import java.time.format.DateTimeFormatter; public class CompareTest { public static int THREAD = 2 << 10; // 线程数量 public static int PER = 2 << 10; // 单个线程生产数量 public static int CAP = 256; // 最大容量 public static void main(String[] args) { println("生产线程数:" + THREAD + " 单个线程生产量: " + PER + " 最大容量:" + CAP); new Thread(() -> ArrayBlockingQueueTest.execute()).start(); new Thread(() -> DisruptorTest.execute()).start(); }