【数据结构】Disruptor环形数组无锁并发框架阅读

Disruptor 是苹国外厂本易公司LMAX开发的一个高件能列,研发的初夷是解决内存队列的延识问顾在性能测试中发现竟然与10操作处于同样的数量级),基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCn演讲后,获得了业界关注,201年,企业应用软件专家Martin Fower专门撰写长文介绍。同年它还获得了Oradle官方的Duke大奖。目前,包括Apache StomCame、 L0g4 2在内的很多知名项目都应用了Disrupior以获取高性能。注意,这里所说的队列是系统内部的内存队列,而不是Kaka这样的分布式队列。
Github: https://github.com/LMAX-Exchange/disruptor
Disruptor实现了队列的功能并且是一个有界队列,可以用于生产者-消费者模型。

Disruptor的设计方案

Disruptor通过以下设计来解决队列速度慢的问题:

环形数组结构


为了避免垃圾回收,采用数组而非链表。同时,数组对处理器的缓存机制更加友好(空间局部性原理)。

元素位置定位

数组长度2n,通过位运算,加快定位的速度,下标采取递增的形式,不用担心index溢出的问题。index是ong类型,即使100万QPS的处理速度,也需要30万年才能用完.

无锁设计


每个生产者或者消费者线程,会先申请可以操作的元素在数组中的位置,申请到之后,直接在该位置写入或者读取数据。


利用缓存行填充解决了伪共享的问题

利用缓存行填充,定义了可为null的七个元素填充一个空的缓存行。
​​​​​​​protected long p1, p2, p3, p4, p5, p6, p7;


实现了基于事件驱动的生产者消费者模型 (观察者模式)


消费者时刻关注着队列里有没有消息,一旦有新消息产生,消费者线程就会立刻把它消费

RingBuffer数据结构


使用RinaBufer来作为队列的数据结构,RinaBuffer就是一个可自定义大小的环形数组。除数组外还有一个席列号(seouence),用以指向下一个可用的元素,供生产者与消费者使用,原理图如下:

 

Disrupior要求没置数组长度为2的次幕。

在知道索引(ndex)下标的情况下,存与取数组上的元素时间复杂度只有0(1),而这个index我们可以通过序列号与数组长度取模来计算得出,index=sequence % entries.length。也可以用位运算来计算效率更高,此时aray.length必须是2的幂次方, index=sequeoe&(entres.length-1)

当所有位置都放满了,再放下一个时,就会把0号位置覆盖掉。

问题: 能覆盖数据是否会导致数据丢失呢?
要覆盖数据时,会执行一个策略,Disruptor给提供多种策略,比较常用的:


1,BlockingWaistrategy策路

常见且默认的等待策略,当这个队列里满了,不执行覆盖,而是阻塞等待,使用ReenranLock+Condition实现阻塞,最节省COU,但高并发场景下性能最差。适合CPU资源紧缺,吞吐量和延迟并不重要的场景。


2,Sleepinowaitstraterv策略

会在循环中不新等待数先进行自等待如果不功,则使用Thread,veld让出CPU 并最终使用LockSuppor.parkNanos(1L)进行线程休眠,以确保不占用太多的CPU资源。因此这个策略会产生比较高的平均延时。典型的应用场景就是异步日志。

3,YeldingWaistrate策略

这个策略用于低延时的场合。消费者线程会不新循环监控缓中区变化,在循环内部使用Thread,yed0让出CPU别的线理执行时间。如果要一个高性能的系统,并且对延时比较有严格的要求,可以考虑这种策略。

4,BusySpinwaitstrategy策略

 采用死盾环,消费者线程会尽最大努力监控缓冲区的变化。对证时北常苛刻的场是使用。CPU核数以须大于消费者线理数量。推荐在线程绑定到固定的CPU的场景下使用。

Disruptor 核心概概念


RingBuffer (环形缓冲区): 基于数组的内存级别缓存,是创建sequencer(序号)与定义WaitStrategy(拒绝策略)的入口。
Disruptor (总体执行入口): 对RingBuffer的封装,持有RingBuffer、消费者线程池Executor、消费之集合ConsumerRepositorv等引用。
Sequence (序号分配器) :
对RingBufer中的元素进行序号标记,通过顺序递增的方式来管理进行交换的数据(事件EVent),一个Sequence可以跟踪标识某个事件的处理
进度,同时还能消除伪共享。
Sequencer (数据传输器) :Sequencer里面包含了Sequence,是Disruptor的核心,Seauencer有两个实现类: SingleProducerSequencer(单生产者实现)MultiProducerSeguencer(多生产者实现),Seguencer主要作用是实现生产者和消费者之间快速、正确传递数据的并发算法SequenceBarier(消费者屏): 用于控制RingBufer的Producer和Consumer之间的平衡关系,并且决定了Consumer是否还有可处理的事件的逻辑。WaitStrategy(消费者等待策略): 决定了消费者如何等待生产者将Event生产进Disruptor,WaitStrategy有多种实现策略Event: 从生产者到消费者过程中所处理的数据单元,Event由使用者自定义。
EventHandler: 由用户自定义实现,就是我们写消费者逻辑的地方,代表了Disruptor中的一个消费者的接口。
EventProcessor:这是个事件处理器接口,实现了Runnable,处理主要事件循环,处理Event,拥有消费者的Sequence 。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/68303.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MinGW-W64 下载、安装与配置(支持最新版的GCC,目前 GCC 13.2.0)

文章目录 一、简介1. MinGW 和 MinGW-W64 区别和联系2. MSVCRT 和 UCRT 介绍 二、下载1. 从 sourceforge.net 下载2. 从 github 下载3. 从 镜像站点 下载4. 自己编译 三、安装与配置1. 在线安装2. 离线安装3. 环境配置 四、总结 一、简介 1. MinGW 和 MinGW-W64 区别和联系 M…

数组slice、splice字符串substr、split

一、定义 这篇文章主要对数组操作的两种方法进行介绍和使用,包括:slice、splice。对字符串操作的两种方法进行介绍和使用,包括:substr、split (一)、数组 slice:可以操作的数据类型有:数组字符串 splice:数组 操作数组…

【go语言学习笔记】04 Go 语言工程管理

文章目录 一、质量保证1. 单元测试1.1 定义1.2 Go 语言的单元测试1.3 单元测试覆盖率 2. 基准测试2.1 定义2.2 Go 语言的基准测试2.3 计时方法2.4 内存统计2.5 并发基准测试2.6 基准测试实战 3. 特别注意 二、性能优化1. 代码规范检查1.1 定义1.2 golangci-lint1.2.1 安装1.2.2…

vue3 + ts+element-plus学习笔记

子组件通过defineProps方法接收父组件传递过来的数据,是vue3中提供的方法,不需要引入,直接使用 方法的写法: const onClick (){... }自定义事件: 子组件点击事件 全局事件总线 mitt 兄弟组件之间的事件&#x…

【福建事业单位-资料分析】03 比重和平均数

【福建事业单位-资料分析】03 比重和平均数 一、比重(现期比重,基期比重、两期比重)1.1 现期比重增长贡献量,利润率 1.2基期比重(用现期和增长率逆求)1.3两期比重(难点重点)——比较…

基础实验篇 | QGC实时调整控制器参数实验

PART 1 实验名称及目的 QGC实时调整控制器参数实验:在进行硬件在环仿真和真机实验时,常常需要在QGC地面站中观察飞行状态,并对控制器参数进行实时调整,以使得飞机达到最佳的控制效果,但是,在Simulink中设…

改进的麻雀算法优化最大相关峭度解卷积(SCSSA-MCKD),实现早期微弱故障诊断,MATLAB代码实现

01 引言 由于一些设备的早期故障产生的冲击十分微弱,易被系统噪声干扰,如何有效地对设备的原始故障信号进行降噪并增强信号中微弱冲击成分,是进行该类部件早期故障诊断的关键。 最大相关峭度解卷积(MCKD)通过解卷积运算…

logstash日志换行处理小解

logstash主用于日志实时数据收集、解析,并将数据转发的工具,内置的功能也相当强大。但,同时意味着,他可能接收到各种情况的数据。 此处,我们主要讲解我实际使用中,碰到的一个小问题,换行(\n)。…

Zabbix监控系统详解及配置

前言 作为一个运维,需要会使用监控系统查看服务器状态以及网站流量指标,利用监控系统的数据去了解上线发布的结果,和网站的健康状态。利用一个优秀的监控软件,我们可以: 通过一个友好的界面进行浏览整个网站所有的服务…

JavaScript应用:五子棋游戏实战开发

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责…

MChat-Gpt V1.0.0 (将ChatGpt机器人接入内网供全体使用)

Github>https://github.com/MartinxMax/MChat-Gpt 首页 MChat-Gpt V1.0.0将ChatGpt机器人接入内网供全体使用 你需要一个ChatGpt账户如果您在中国则需要使用代理访问,设置TUN代理模式 安装依赖 选择你的系统进行安装 服务端配置 #python3 ChatGpt_Server.py -h 使用&a…

汉字形近字(OCR)

近期做中文OCR识别的优化,抓破头皮却收获甚微。 为了百尺竿头更进一步,遂将目光聚焦在中文汉字特有的形近字和生僻字问题上,于是怒发整理形近字大全(花了不少刀),希望对同行朋友们也有帮助: 地表…

【BMC】OpenBMC开发基础3:引入新的开源配方

引入新的开源配方 前面介绍了如何在OpenBMC中通过新建配方引入自己的程序,也介绍了如何修改原有的程序,下面要介绍的是如何引入开源的新程序,这在OE系统上是很方便的,重点就在于引入新的配方。 OE为了方便开发者使用&#xff0c…

【如何在Linux环境下进入Docker容器中的MySQL】

如何在Linux环境下进入Docker容器中的MySQL 查看所有容器 docker ps进入容器 docker exce -it {NAMES/CONTAINER ID} bash根据容器别名获取容器ID都可以进入到容器当中 3. 输入MySQL的账号和密码登录MySQL mysql -uroot -p{password}

竞赛项目 深度学习的视频多目标跟踪实现

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的视频多目标跟踪实现 …

HTTP代理授权方式介绍

在网络爬虫过程中,我们经常需要使用HTTP代理来实现IP隐藏、突破限制或提高抓取效率。而为了确保代理的正常使用,并避免被滥用,代理服务商通常会采用授权方式。在本文中,我们将介绍几种常见的HTTP代理授权方式,以帮助你…

Goland报错 : Try to open it externally to fix format problem

这句报错的意思也就是 : 尝试在外部打开以解决格式问题 解决方案 : 将图片格式该为.png格式,再粘贴进去就可以了! 改变之后的效果 : 那么,这样就ok了

服务器数据恢复-断电导致ext4文件系统文件丢失的数据恢复案例

服务器数据恢复环境: 一台服务器挂载一台存储设备,存储中划分一个Lun;服务器操作系统是Linux centos,EXT4文件系统。 服务器故障&分析: 意外断电导致服务器操作系统无法启动,系统在修复后可以正常启动&…

计算机网络(7) --- UDP协议和TCP协议

计算机网络(6) --- https协议_哈里沃克的博客-CSDN博客https协议https://blog.csdn.net/m0_63488627/article/details/132112683?spm1001.2014.3001.5501 目录 1.补充知识 1.PORT端口号 2.端口号范围划分 3.知名端口号 2.UDP协议 1.UDP报头 2.U…

【算法】逆波兰表达式

文章目录 定义求法代码思想: 定义 逆波兰表达式也称为“后缀表达式”,是将运算符写在操作数之后的运算式。 求法 *如:(ab)c-(ab)/e的转换过程: 先加上所有的括号。 (((ab)*c)-((ab)/e))将所有的运算符移到括号外面 (((ab) c)* …