借鉴rocketmq

RocketMQ提供P2P模式的消息队列服务,支持一对一和发布/订阅模式。为解决单点故障,RocketMQ引入Master-Slave热备机制,采用同步双写或异步复制方式保证数据安全。在持久化方面,RocketMQ借鉴Kafka的文件组织,利用Linux的pagecache优化性能,并使用零拷贝技术提高消息消费效率。此外,还探讨了文件系统选择、优化策略和避免文件读写冲突的方法。

RocketMQ调研

P2P模式?

rocketMQ说的p2p是点对点的意思,是消息队列的一种模式,和我们说的p2p协议没有什么关系。

消息队列有两种模式,rocketmq都支持。

① 基于queue的一对一的模式:一个消息只有一个真正的消费者,因为消息取走了之后,消息就不会在broker存在了

② 基于topic的发布/订阅模式:一个消息有多个消费者,消息会一直持久化在broker中,通过一定的策略来删除消息,这个通过rocketmq的参数来配置,例如:超过几天?或者磁盘存储达到一定的阈值等。

可用性 单点故障

机器无法开机(可能是 cpu、主板、内存等关键设备损坏),磁盘设备损坏,都会产生单点故障,且机器无法恢复,一旦发生,在此单点上的消息全部丢失?怎么办?

RocketMQ引入了热备机制,brokermaster/slave模式。

一个 Master 可以对应多个Slave,但是一个Slave 只能对应一个MasterBroker Slave 是通过指定相同的brokerName 参数来配对,同一Master 下的多个Slave 通过指定不同的BrokerId 来区分。

Masterslaveip都是在配置文件中就区分好的,所以这也是rocketmq不需要zk来协调的原因之一,因为不需要master的选举。

Masterslave之间的同步有2种方式:

① 同步双写

a) 每个 Master 配置一个Slave,有多对Master-SlaveHA 采用同步双写方式,主备都写成功,向应用返回成功。

b) 优点:数据与服务都无单点,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高

c) 缺点:性能比异步复制模式略低,大约低 10%左右,发送单个消息的RT 会略高。目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能。

② 异步复制

a)    每个 Master 配置一个Slave,有多对Master-SlaveHA 采用异步复制方式,主备有短暂消息延迟,毫秒级。

b) 优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为 Master 宕机后,消费者仍然可以从Slave 消费,此过程对应用透明。不需要人工干预。性能同多Master 模式几乎一样。

c) 缺点:Master 宕机,磁盘损坏情况,会丢失少量消息。

持久化 文件组织

RocketMQ 参考了 Kafka的持久化方式,将消息持久化到文件中,充分利用 Linux文件系统内存 cache(即提高pagecache的命中率)来提高性能。

 

总结Rocketmq的存储特点:

零拷贝技术

Consumer 消费消息过程,使用了零拷贝技术,因为有小块数据传输的需求,效果会比 sendfile 更好,所以RocketMQ选择了mmap+write方式。

① 优点:即使频繁调用,使用小块文件传输,效率也很高

② 缺点:不能很好的利用 DMA 方式,会比 sendfile 多消耗CPU,内存安全性控制复杂,需要避免JVM Crash问题。

文件系统

建议选择ext4文件系统,删除文件的实时性强。

调优:文件系统的io调度算法需要调整为deadline,因为deadline 算法在随机读情况下,可以合并读请求为顺序跳跃方式,从而提高读IO 吞吐量。

数据存储目录

|-- TopicA     topoic

| |-- 0        queue=partitionkafka

| | |-- 00000000002604000000

| | |-- 00000000002610000000

| | `-- 00000000002616000000

| |-- 1

| | |-- 00000000002610000000

| | `-- 00000000002616000000

|-- TopicB

| |-- 0

| | `-- 00000000000732000000

| |-- 1

| | `-- 00000000000732000000

| |-- 2

| | `-- 00000000000732000000

  •  一个topic对应一个文件夹,一个topic对应至少一个队列
    • 一个队列对应一个子文件夹
    • 每个子文件夹中含有很多个log文件
    • log文件超过一定阈值时,重新写一个log文件
    • log文件以其存储的最小的offset来命名

 

对比Kafka

  •  一个分区对应一个文件夹,文件夹的名字以topic+序号命名
  • 一个分区包括至少一个indexlog文件,一个index文件对应一个log文件
  • log文件超过一定阈值时,重新写index文件和log文件
  • index文件是一个稀疏索引,index文件以最小的offset命名
  •  log文件以最小的offset命名

 对消息的查找:先对index文件的名字进行2分查找,再对index文件内容的offset进行2分查找。。。。

 

文件读写冲突?

写文件的时候,如果消费者在读怎么办?

依赖于操作系统对文件读写操作的处理,,,永远一个一个进程在写文件如果其他进程需要访问文件,只能是读,或者是再创建一个副本,写文件。(读写锁+写时复制) 

提高pagecache?

  想要提高pagecache的命中率,即尽量让访问的页在物理内存中,而不是在虚拟内存中,减少IO 读操作,所以从硬件的角度,当然是内存越大越好。

而在软件角度,rocketmq有以下策略:

尽量顺序读

 如果需要随机读的话:

访问 PAGECACHE 时,即使只访问 1k 的消息,系统也会提前预读出更多数据,在下次读时,就可能命中内存。

 随机访问 Commit Log 磁盘数据,系统 IO 调度算法设置为NOOP 方式,会在一定程度上将完全的随机读变成顺序跳跃方式,而顺序跳跃方式读较完全的随机读性能会高5 倍以上。

 

 

可能的优化策略

1.线程绑定核+线程池(取模)

a) 将每个线程绑定核,一个函数就可以

b) 优势:避免线程核间调度

2.改用互斥锁为读写锁

a) 读读场景的线程可以并行

3.使用xxhash代替crc算法,性能可以提高很多

a) 参考链接:https://cyan4973.github.io/xxHash/

4.使用topic划分多个逻辑队列(链表)

a) 避免topic的多次字符串的比较

5.改用STLdeque来替代MESA list

a) Deque类似于vector,可以支持随机访问

b) 常量时间内在头部和尾部插入,删除元素

6.改用跳表来代替MESA list

a) 跳表可以高并发+logn)的随机访问

b) 不能删除元素 

i. 设为标志位,当内存数据达到一定阈值时,写到磁盘或者持久化到leveldb中(hbase也是这样做的)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值