作用
解耦、异步、削峰 //要深刻的理解这六个字真言,最重要的是场景,把场景架构图背诵 www.cnblogs.com/rjzheng/p/8…
总结
1.最重要的是应用之家进行解耦
2.其他的作用都只是解耦之后附带的作用
四大角色
1.注册中心
2.服务器
3.生产者
4.消费者
部署步骤
1.注册中心先启动
2.然后再启动服务器broker,broker注册到注册中心
3.生产者从注册中心获取broker集合,负载均衡选择一个broker,写数据到broker
4.消费者根据主题名字 + 消费者组名字,找到是哪一个消息队列(逻辑数据),从而找到物理数据
集群
架构图
节点通信
1.注册中心和服务器通信
所有的服务器注册到每一个注册中心,也就是说,每个注册中心包含所有的服务器且数据一样。
2.注册中心节点之间不通信
每个节点都保存了服务器集合,每个节点保存的是一样的数据。
但是每个节点之间不通信,是互相独立的,不像redis哨兵或者zookeeper会有选举leader节点的过程。
流程
1)生产者:按什么算法选择一个注册中心——》注册中心:按轮询算法选择一个服务器——》服务器
2)消费者:按什么算法选择一个注册中心——》注册中心:按轮询算法选择一个服务器——》服务器
生产者和消费者,都是先从注册中心进行通信取得服务器集合并且存储到自己的本地,然后再挑选一个服务器,最后直接和服务器通信。
服务器节点挂了怎么办?
每个注册中心,都从服务器集合删除挂了的服务器。因为每个注册中心都和所有服务器通信。
注册中心挂了怎么办?
生产者或者消费者,从注册中心集合删除挂了的注册中心节点。
注:1.dubbo/zookeeper,服务提供者或服务消费者,流程也是先经过注册中心,然后再到服务器。但是zookeeper注册中心集群的时候,是由唯一的leader节点来接受服务提供者或服务消费者的请求,如果leader节点挂了,那么follower集合会选举出来一个新的leader,然后就是新的leader接受请求。
2.注册中心如果挂了,不会即时通知broker;而是懒通知,即当生产者/消费者再次请求获取服务器集合时,才知道注册中心挂了。
注册中心的发展历史
1.早期版本metaQ
没有注册中心,需要引入第三方注册中心zookeeper。像redis一样引入第三方注册中心zookeeper。
2.后期版本RocketMQ
RocketMQ自己实现了注册中心。
RocketMQ的整体架构设计
下图为大家清晰地展示了RocketMQ的几个组件,分别是nameserver、broker、producer和consumer。nameserver主要负责对于源数据的管理,包括了对于Topic和路由信息的管理,broker在启动的时候会去向nameserver注册并且定时发送心跳,producer在启动的时候会到nameserver上去拉取Topic所属的broker具体地址,然后向具体的broker发送消息。
源数据,包括:
1.路由
2.topic
由此二者可以使得生产者和消费者找到哪一个消息队列和哪一个broker的物理数据。
上图的流程步骤说明
1.服务器broker向所有注册中心注册
2.消费者从注册中心获取所有服务器集合
3.消费者,从本地存储的服务器集合按轮询算法选择一个服务器
4.生产者从注册中心获取所有服务器集合
5.生产者,从本地存储的服务器集合按轮询算法选择一个服务器,写数据到该服务器
最终,生产者写数据到服务器之后,服务器主动推数据到消费者!
同一个消息被消费几次的问题?
想要弄懂这个问题,是需要先把应用场景弄懂,而不是先去背诵一些概念/模式,什么点对点、广播模式、集群模式。
消费几次的问题本质是什么
就是一个数据需要被几个消费者消费的问题,一般来说是有多个消费者去消费同一个数据,那么就是消费多次。如果只有一个消费者,那么就是只消费一次。
应用场景
就是什么系统,消费几次的问题。主要是要思考和理解这个。
按一个消息被消费几次划分
1.一次
集群模式
2.多次
广播模式
注:名字取的一点都不好,消费几次就叫消费几次,还取个几把名字叫什么消费模式——模式一出来,就不知所云!
最佳实践
1.一般比较常用的是集群模式,集群就是一个消费者组对主题的同一个数据只消费一次。
2.广播模式是,同一个组的每个消费者都会消费一次。
工作使用-支付系统
一般来说,都是同一个数据会被消费多次,因为需要把同一个数据通知给不同的系统。
如果有的服务是集群,那么同一个分组的集群服务虽然有多个服务,但是只会被其中的一个服务消费一次。
多个消费者消费同一个数据,如何实现区分不同消费者的进度?
每个消费者单独维护一个进度/偏移量。
主题和次数的关系
主题就是数据,比如订单主题就是订单数据,然后会有多个系统/消费者消费订单数据,也就是订阅这个主题下的所有订单数据。
代码
1.生产者写数据到某个主题
2.消费者订阅某个主题 //创建消费者的时候,可能会配置分组
3.消费者使用回调类.回调方法(消息数据)来消费数据
分组和次数的关系
就是同一个主题的同一个数据,有的是同一个服务的集群,既然是属于同一个服务,肯定是只需要消费一次就够了。
代码
同上 //创建消费者的时候,有一个配置类参数,可以配置很多参数,包括是否分组
总结
在消息中间件里,消费一次还是多次,有专门的术语,就是消费次数的模式:
1.广播
广播指的其实就是,主题的数据,所有订阅者/消费者都会去消费某一个数据,即每个消费者消费一次。例如,商家和代理商后台系统都会消费同一笔订单数据。
2.集群/分组
指的是同一个服务可能是集群模式部署,如果是集群模式服务,那么其中肯定只能有一个服务消费数据,这个时候就适合设置分组模式/集群模式。
其实把原理和本质弄清楚了,概念就很容易对上。要先理解原理和本质的思想,可以先自己去想都没有关系,而不是反过来先去记概念,因为概念不重要,你要实现什么功能才重要。
消息可靠性
消息确认机制(ACK机制)
有三种情况
1.消费者消费成功
消费者消费消息的时候,和broker/服务器之间有确认成功机制,即消费者消费成功,就写消费成功ACK到broker,确保每条消息至少被消费一次。
2.消费者消费失败/异常
如果由于消费者本身消费异常(比如,消费者端代码异常),导致消费数据失败,会发送消费失败给服务器,服务器重发数据。具体实现机制是什么?使用retry机制,就是把数据丢到retry主题队列,retry主题名字由retry主题名字组成。
重发/重试retry。重发几次?时间间隔?时间逐渐递增。
3.消费者消费成功,但是成功响应的时候,服务器没有收到成功响应
如果消息成功,但是由于网络原因(断网了或者停电关机了),导致确认失败,那么消费者将会重复消费。怎么解决?消费者端幂等处理重复消息。
消息确认机制
即ACK机制。
消费者接收到消息,需要确认。具体确认方法,就是会响应付给服务器。
服务器收到消息之后,才会真正的更新偏移量。
重复消费
1.发生场景
消费者已经消费,但是在响应的时候,断网了,服务器没有收到响应,那么服务器就认为消费者没有收到消息,于是便重发消息。
2.问题
这个时候就存在消费者重复消费消息的问题。
3.如何解决
消费者幂等。具体解决方法?消费者接受到消息的时候,1.展示给用户2.存储到数据库。所以,但凡是处理幂等的问题,就是通过比较当前请求数据和数据库里的数据来判断是否是同一个数据。
工作实践-支付系统
流程
1.订单支付成功之后,生产者发送消息到消息中间件
2.后台系统-商家、代理商,都是消费者都会收到消息数据,都是消费数据 //后台系统都是单点,所以不同消费者系统各自消费一次同一个数据
注:app通知 //app又是另外的一套机制:手机硬件 + 极光推送
代码
1.写 //订单支付成功消息<topic名字,order对象>
2.读 //回调类的回调方法,消费数据
参考
blog.csdn.net/gwd11549783…
blog.csdn.net/gwd11549783…
写和读
写
写就是生产者——》服务器。
服务器如何存储数据?
消息队列。即使用队列这种数据结构来存储数据。
读
读就是消费者——》服务器。
服务器和消费者如何保存消费进度?
基于偏移量offset。
如果有多个消费者消费,那么为每个消费者保存单独的进度。
消费者把数据存储在哪里?
1.消费者订阅主题
2.生产者写数据
3.消费者读数据
消费者把读到的数据存储在哪里?还是直接消费?具体是在哪里消费数据的?具体是如何消费的?代码?一般来说,像这种多步骤的逻辑,都是通过回调类/回调方法。因为这里也有两步就是1.消费者先订阅主题2.消费者消费数据。而且消费者消费数据的时候,是等到有数据才消费,这两个步骤是有先有后,后面一个步骤是有延后的时间,所以就是通过回调来消费数据。
代码例子
rocketmq.apache.org/docs/order-… //官方例子 //步骤1.消费者订阅主题 2.消费者注册回调类/回调方法 3.回调方法消费数据
消费者集群-同一个服务集群部署?
消息中间件服务器同一时间,只能被一个消费者消费。但是,一个消费者可以消费多个多个消息中间件服务器。
如何解决高性能读写数据的问题?
内存和文件映射,减少数据的复制。
如何确保数据按顺序消费的问题?
一般是topic的某几个数据,要确保顺序消费,要做到两点:
1.顺序写入同一个消息队列
2.同一时间,只能有一个线程消费同一个消息队列,也就是说,要对同一个消息队列进行同步处理
具体怎么做?
写的时候,判断orderId,如果是同一个orderId,那么写入同一个消息队列,而不是随机选择。
读的时候,同步处理即可。
高可用?
集群 + 负载均衡
同步异步?
指的是发送数据的时候,是同步,还是异步。
最终一致性?
消息中间件要解决的问题就是非实时数据的最终一致性问题。
批量发送数据?批量发送数据如何解决一致性?
?
事务?
什么是事务消息? 事务消息就是,1.发送成功2.其他操作成功3.第二次发送commit。即二次提交,二次提交的原因是因为有其他操作,其实就是类似于分布式事务,有两个sql操作在不同的机器,逻辑基本上是一样的。
支付的分布式事务是这样的1.第一个操作成功2.第二个操作成功3.提交事务。但是具体实现的时候是,分布式事务是分布式事务,消息是消息,这两个是分开的,这里说的分开指的是没有把消息放在分布式事务里,也就是说分布式事务的组成不包含消息,是否发送消息只是一个简单的if else判读,分布式事务成功commit就发送消息,否则不发送消息。
支付的消息是广播,就是同一个消费者组都会消费这个消息,主要就是商家和代理商系统。
最新版本才支持事务消息。由于事务消息功能支持的不好,因为与高性能相矛盾,好像又撤了。
索引
消息队列就是对物理数据的索引。
刷盘
由于消息存储这一块使用了文件内存映射机制,所以持久化的时候有两种机制:
1.同步
2.异步
同步,就是立即把内存数据写到映射文件。
异步,就是不是立即写。
复制
就是从复制主的数据。
复制很简单,其实就是两个系统之间的通信,怎么通信?就是tcp套接字连接
主挂了,从晋升为主,这个是怎么实现的?
不管是主还是从,其实都是broker,broker启动的时候都注册到注册中心。
生产者写的时候,流程是:生产者——注册中心:获取broker集合,负载均衡选择一个——broker。broker和注册中心保持通信,broker挂了,注册中心删除该broker,所以生产者写数据到从即可。
如何保证主从复制时数据的一致性问题?
既然是复制,就有时间延迟,这是不可避免的。只能尽量优化复制效率。
知识点
一些概念
1.主题
相当于是数据集合
2.生产者
作用是写数据
3.消费者
作用是读数据
4.消息队列
对应的类是MessageQueue,包含字段:1,哪一个机器 2,哪一个逻辑文件 3,哪一个物理文件。这样就可以唯一定位到对应的数据。
注:
物理数据文件是主题文件,按实际数据结构存储实际数据,目录是commitlog目录/主题名字/XXX。
逻辑数据文件是消息队列文件,按逻辑数据结构存放逻辑数据(映射到实际文件的实际数据),目录是consumequeue/queueid/XXX。
5.注册中心
作用是协调broker。
RocketMQ自己实现。没有使用Zookeeper,因为引入第三方中间件,会带来不必要的依赖和不稳定的麻烦,越简单越好够用就好。
注:RocketMQ服务器叫broker,broker的角色分主和从。
6.集群
比如二主二从二注册中心
7.主备
比如一个机器上一主一从
一个主题为什么要弄成多个消息队列?
把一个物理的主题变成逻辑的消息队列集合(包含n个消息队列),目的是间接地实现主题的分布式存储,间接的意思是指不是直接把主题分布式的存储在多个机器,而是多个消息队列分布在多个机器。
1.存放数据的物理主题文件只有一个
2.逻辑消息队列有多个,分布式存储在不同的机器。
每个消息队列包含了哪一个机器字段。所以,如果有的消息队列不是存储在本地机器,也可以通过消息队列的哪一个机器字段找到物理主题的那个机器。
多个消息队列文件的数据是一样的吗?
不一样。因为生产者每次写数据到逻辑文件的时候,是随机选择一个逻辑文件,所以每个数据只存放在被选中的那个逻辑文件。
生产者如何写数据?
流程
生产者——随机选择一个逻辑数据文件——物理数据文件
详细步骤
1.生产者
2.逻辑数据文件
随机选择一个逻辑数据文件(消息队列),即从消息队列集合随机选择一个消息队列
3.物理数据文件
写数据到broker
消费者如何读数据?
流程
消费者——遍历逻辑数据文件——物理数据文件
详细步骤
1.消费者
2.遍历逻辑数据文件集合(即消息队列集合)
遍历消息队列集合,多次请求broker。其中必有一个消息队列,可以找到物理数据文件。
3.物理数据文件
从broker读数据
什么是消息队列id?
唯一标识消息队列。
目录是consumequeue/queueid/XXX。
多个消费者如何消费数据?broker如何保存每个消费者的进度?
1.逻辑数据偏移量
2.物理数据偏移量
逻辑数据和物理数据
消息队列流程图
类图
物理数据
主要字段
1.偏移量
2.大小
偏移量是加上大小
逻辑数据
主要字段
1.偏移量
2.大小
偏移量是自增1
逻辑数据所在磁盘位置
数据内容
索引
逻辑数据
磁盘上的逻辑数据
消息队列目录
{
"offsetTable":{
"TopicTest@orderG2":{0:31,1:32,2:33,3:32
}, //主题名字@组名字:{消息队列编号:偏移量}
"%RETRY%orderG@orderG":{0:0
},
"TopicTest@orderG":{0:31,1:32,2:33,3:32
},
"%RETRY%orderG2@orderG2":{0:0
}
}
}
注:偏移量是在逻辑数据文件里的偏移量,根据偏移量,可以找到哪一个逻辑数据。
数据结构
包含主要字段
1.物理偏移量
2.大小
物理偏移量定位到哪一个数据的起始位置,大小定位结束位置。
消费者是如何定位到哪一个消息队列的?
消息/消息队列存储在注册中心。
物理数据
磁盘上的数据文件。和逻辑数据的本质区别?
笔记
注册中心不需要持久化数据,数据都是在内存。数据就是ip。
IP的作用就是用来路由服务器的。
所谓路由就是负载均衡选择一个服务器。
所有实时的数据都不需要持久化,非实时的数据才需要持久化。
比如,消息中间件的数据,写和读是不在同一个时刻,当然不能太慢,而是说允许几十秒到几分钟的延迟。所以中间件的数据需要持久化。
RPC都是实时调用,不存在什么持久化。
注册中心的数据,都在内存,实时调用,实时通信,不存在持久化。
负载均衡算法就3种 1.余数 2.一致性Hash环 3.槽
余数,就是用Hash除以机器数量,得到一个余数。但是有个问题,不够均衡。
一致性Hash环,主要是为了解决增加一个节点或减少一个节点带来的问题。最终实现,某个节点的加或减,影响的数据有限。但是有个问题,节点少的情况下,每个节点的数据多,那么增或减一个节点,影响的数据比较多。所以,解决了均衡的问题,但是没有解决节点少这种情况的均衡问题。
槽,主要是解决节点少不均衡的问题,那我们换个思路,就是增大节点的数量,具体做的时候不能增大实际节点的数量,那么就只能增大虚拟节点的数量,这个虚拟节点算是一个中介,流程是:数据-中介节点-实际节点。
服务器和注册中心具体是怎么通信的?其实就是调用方法,和别的没有任何区别,什么心跳啊 心跳包啊,都一个意思,不管叫什么名字,都是调用方法,输入数据和输出数据。
1.余数 增加一个节点或减少一个节点,影响数据太多。 2.一致性Hash 增加一个数据或减少一个节点,影响数据比较少。 但是,如果节点比较少,那么还是影响的数据比较多。 3.中介槽 即便是节点比较少,影响的数据也比较少。 通过引入中间节点的办法。中间节点1万个,这样单个节点影响的数据比较少。
所谓长连接,就是你不断开,我也不断开。 TCP套接字,有个close方法,主要不主动调用关闭方法,套接字就一直处于连接状态,这就是长连接。
zookeeper注册中心是有把数据持久化到磁盘的,比如,RPC dubbo和zookeeper搭配使用。
为什么呢?因为RPC的数据是非实时,RPC的数据就是IP-port-类-方法。生产者写数据,消费者稍后才调用方法。
所谓幂等,就是在处理数据的时候先验证之,如果已经处理过,比如,和数据库的数据比较,如果已经存在,那么就直接返回,不做处理,这样就相当于解决了数据的重复处理的问题。
支付场景也有这种需求。
消息中间件也有这种需求,解决办法的思路是一样的,就是先校验之,如果数据库里已经有了数据就直接返回不做处理。
支付幂等场景?支付是如何解决幂等的?
消息中间件生产者写数据重复?为什么会重复?
消息中间件消费者如何解决读重复数据的问题?消费者幂等。
幂等的前提是,当前数据在数据库存在,也就是说,必须有一个ID字段相同,才能知道是幂等的。
支付的幂等是,扫码的时候,order和orderId已经生成。后面点击提交按钮多次提交或者点击支付按钮多次支付,在后头始终是一个order和orderId。
下游商家来了一个订单数据,支付公司生成自己的订单数据,缓存数据库里有ID/order,ID什么时候产生的? 对于扫码支付而言,不是下游商家,而是微信客户端。下游商家只是二维码url的一个字段-商家号。根本就没有什么下游商家。
不是order的ID,是UUID,这个UUID在服务器和客户端,具体的流程是这样的,我们只需要关注两个步骤: 1.点击提交按钮,提交订单 2.点击支付按钮,支付订单
第一步,服务器生成UUID,缓存数据库保存UUID/order。
以上是错的。
两个重要步骤是1.扫码2.点击支付按钮。二维码是服务器的一个请求url,包含了商家号字段。
扫码支付的流程
消息中间件 生产者发写数据,为什么会重复? 断网是不可避免的,这个是由网络的硬件物理特性决定的,只能尽量避免减少损失。那玩游戏是怎么处理这种实时的对网络性能要求极高的情况? 断网。写了两次,因为也没有对方的回应,所以就再写了一次。
生产者写的时候 重复?主要是重复什么呢?就是两条一模一样的数据被写入了物理数据文件。
那么消费的时候,要解决重复消费的问题,怎么解决?幂等。由于两个数据的ID字段一样,所以,处理过了就不再处理。
网络波动是什么? 就是断网了。临时断网了。
网络不可达是什么? 断网了
网络波动、跳Ping、丢包、掉线 cs.xunyou.com/html/39/1/4…
什么是顺序消费? 就是有的数据,因为业务上的要求,必须要按顺序消费,比如,订单1.未支付2.已支付。
顺序消费分类?从数据量来划分1.所有数据,即所有主题的所有数据2.某个主题的数据3.某个主题的包含同一个字段值的某几个数据,比如,order主题里面只有包含了相同orderID的数据才需要顺序被消费,不同的order是没有必要按顺序来消费的。
一般不会所有topic,而是topic的某几个数据。 同一个消息队列加锁,同一时间只有一个消费者能够消费该消费队列的数据。
如何解决顺序消费?
如果是所有topic,那么所有topic 即topic集合的数据结构应该是队列,先进先出,这样就保证了所有topic的顺序。如果是topic下面的数据,那么同一个消息队列的数据同步,同一时间只能有一个线程消费。
网络的稳定性非常重要,不然打游戏都打不了。 1.宏观 2.微观
宏观就是不能断网。
微观就是网络硬件本身的特性决定的,不能做到100%,总有一个丢包率,总有一个网络抖动的时刻,但是基本上影响不大。
生产者和消费者分别是如何选择消息队列的?负载均衡。 首先,生产者是负载均衡,之所以弄一个中间的东西出来也就是消息队列出来,目的也是为了分布式。 消费者是根据什么知道数据是在哪一个消费队列? 肯定是消息的某个唯一标志和消息队列唯一标志关联了起来。
集群-消息队列的数量和节点broker的数量
几种情况
1.少
2.一样
3.多
节点的数量少,一个节点多个消息队列。
一样,一个节点一个消息队列。
节点多,有的节点就没有消息队列,即没有流量请求。如果是后面增加的节点,那么就是后面增加的节点都没有流量请求。
高级知识点
多中心多活、灰度发布、熔断机制、消息存活期、流量的权重、消息去重、惊群效应问题的解决、背压模式、消息服务治理、MQTT消息服务
搭建环境
步骤
1.先启动注册中心
2.再启动服务器
先启动注册中心,再启动服务器broker,broker就注册到了注册中心,生产者写数据的时候,就从注册中心获取broker集合,负载均衡选择一个broker,往里面写数据即可。 启动完成注册中心和broker之后,
注册中心
所有的节点,包括broker和生产者/消费者,都要和注册中心通信,各自的通信想要获取的数据也不同。但有一点,注册中心的数据一样,所以解决了单点挂了的问题。
索引
数据结构
是hashmap,不是树。
与kafka的区别
编程语言
RocketMQ编程语言是java。
注册中心
RocketMQ是自己开发。
kafka是zookeeper。
主从
目前主从,如果主挂了,从只能读。没有实现自动晋升从为主。如果要实现自动晋升,需要开发者自己实现。
文件内存映射
作用是节省数据复制的次数,从而提高数据的读写速度。
具体是怎么节约的?细节?直接把磁盘文件和用户进程缓冲区内存建立联系,数据不经过内核的缓冲区,减少了一个环节的数据复制,即内核进程缓冲器和用户进程缓冲区二者之间的内存的数据复制。
单机数据量
万级别
阿里中间件博客文章总结
RocketMQ的技术概览 请配图同时对RocketMQ的架构进行说明;请对消息的产生、传输和消费流程进行说明,最好也可以配图。
在我们看来,它最大的创新点在于能够通过精巧的横向、纵向扩展,不断满足与日俱增的海量消息在高吞吐、高可靠、低延迟方面的要求。
目前RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分构成,如下图所示。
所有的集群都具有水平扩展能力,无单点障碍。
NameServer以轻量级的方式提供服务发现和路由功能,每个NameServer存有全量的路由信息,提供对等的读写服务,支持快速扩缩容。
Broker负责消息存储,以Topic为纬度支持轻量级的队列,单机可以支撑上万队列规模,支持消息推拉模型,具备多副本容错机制(2副本或3副本)、强大的削峰填谷以及上亿级消息堆积能力,同时可严格保证消息的有序性。除此之外,Broker还提供了同城异地容灾能力,丰富的Metrics统计以及告警机制。这些都是传统消息系统无法比拟的。
Producer由用户进行分布式部署,消息由Producer通过多种负载均衡模式发送到Broker集群,发送低延时,支持快速失败。
Consumer也由用户部署,支持PUSH和PULL两种消费模式,支持集群消费和广播消息,提供实时的消息订阅机制,满足大多数消费场景。
写数据和读数据的几个重要问题
从发送端和接收端来看有如下图所示的几个比较重要的部分。
首先对于发送端而言,需要重点关注是三个部分,一个就是发送失败了怎么办,这里就是send backoff也就是所谓的一种补偿。那么发送失败了,怎样进行补偿呢?比如现在的机制是三次补偿,需要设置每次间隔多少秒,这是就一种很好的补偿机制。还有就是send reliability,也就是发送的可靠性。第三块就是send oneway(即单向发送),也就是在一些大数据场景下不需要响应的情况下,可以采用send oneway的方式来迅速地提高吞吐量。
而对于消费者端而言,有几块也需要重点关注。一个是重复消费问题,一般情况下推荐大家通过存储介质探重。而如果消费失败了或者消费速度太慢怎么办,有什么样的方式可以解决呢?一种方案就是通过并发去解决,可以通过提高并发的通道实现。第三块就是consume batch的问题,在RocketMQ里面默认的batch是32,如果大家觉得自己消息引擎吞吐量比较低就可以提高batch,但是如果不对于服务端的限制进行调整,batch最多也就只能达到32。
总结
1.补偿
补偿机制,就是未成功,就retry。
2.单向发送
就是只管写数据,不需要返回。
3.存储介质探重
就是判断数据库是否存在,如果存在,做幂等处理。所谓幂等,就是数据存在,那么直接返回,什么都不做。
调优
接下来分享一下阿里巴巴内部对于RocketMQ服务端性能调优的几点经验总结。
这几点经验其实都与I/O相关,首先如果要进行I/O操作,那么就无法避免文件句柄的调优,这个是达到一个高吞吐必备的系统调优。
其次CPU的亲和特性,包括线程亲和CPU,内存亲和CPU,网卡亲和CPU,这里面非常有学问。
第三部分就是如何突破内存锁的限制,无锁设计是我们所推崇的。
第四部分就是NUMA架构Disable问题。这里简单提一下NUMA架构,它主要是为了解决CPU访问内存的响应性能问题。因为由于所有CPU都是通过一个内存控制器来读取内存,随着CPU核不断发展,其响应时间上的性能问题越来越明显。
于是,NUMA架构出现了。NUMA会为每个CPU核绑定一部分内存,每次在CPU中运行的线程会优先地去访问该CPU所对应的内存,而当内存不足的时候,会优先把CPU相对应的内存释放掉。NUM这种默认的内存分配算法对于存储类产品而言是存在问题的,所以建议大家对于这一部分进行Disable,当然业界也有很多其他的解决方案,比如打开NUMA中的交叉分配方案。
而通过很多的线上观察,我们发现在线程处理来自外部的请求的时候,对于内存的访问其实都是随机的,所以交叉分配方案可以使得线程对于内存的访问进行打散,具有一定程度上的提升。还有一部分就是PageCache flush调优,因为MQ的存储其实是一个文件系统,那么就避免不了与PageCache打交道,而PageCache里面就有很多可以进行调优的,包括脏页回写,换页机制等,这些都是进行调优的重点。
最后一部分就是对于磁盘的I/O调度的调优,大家都知道在磁盘的I/O调度方面,Linux操作系统默认为我们提供了四种方式,而通过线上的观察以及实验建议大家将默认的调度方式变为Deadline方式,也就是最后期限调度算法,这样就可以有效地避免I/O写请求饿死情况的出现。
消息中间件的两大作用
2.2 低延迟探索之路
RocketMQ作为一款消息引擎,最大的作用是异步解耦和削峰填谷。一方面,分布式应用会利用RocketMQ来进行异步解耦,应用程序可以自如地扩容和缩容。另一方面,当洪峰数据来临时,大量的消息需要堆积到RocketMQ中,后端程序可以根据自己的消费速度来进行数据的读取。所以保证RocketMQ写消息链路的低延迟至关重要。
在今年双11期间,天猫发布了红包火山的新玩法。该游戏对延迟非常敏感,只能容忍50ms内的延迟,在压测初期RocketMQ写消息出现了大量50~500ms的延迟,导致了在红包喷发的高峰出现大量的失败,严重影响前端业务。下图为压测红包集群在压测时写消息延迟热力图统计。
事务
RocketMQ支持事务,包括本地事务和分布式事务。
学习资料
官方
官方文档
rocketmq.apache.org/docs/simple…
官方github
github.com/apache/rock…
网络资料
浅谈消息队列及常见的消息中间件
juejin.cn/post/684490…
消息中间件—RocketMQ消息消费(一)
www.jianshu.com/p/f071d5069…
m635674608.iteye.com/category/32…
自己实现消息中间件
zhuanlan.zhihu.com/p/27693508
阿里中间件
jm.taobao.org/tags/Rocket…
Apache RocketMQ背后的设计思路与最佳实践 jm.taobao.org/2017/03/09/…
源码分析
RocketMQ源码分析之消息发送
zhuanlan.zhihu.com/p/58026650
zhuanlan.zhihu.com/p/58728454
大厂最佳实践
微众银行-消息服务平台建设实践 mp.weixin.qq.com/s/sqBtQNZ6F…
滴滴出行基于 RocketMQ 构建企业级消息队列服务的实践 www.infoq.cn/article/dXJ…
书籍
1.入门
《RocketMQ实战与原理解析》
book.douban.com/subject/302…
2.实现原理
《RocketMQ技术内幕:RocketMQ架构设计与实现原理》
book.douban.com/subject/304…