rocketmq存储结构_谈谈Rocketmq

1、为什么要用MQ?

(1)解耦:如果多个模块或者系统中,互相调用很复杂,维护起来比较麻烦,但是这个调用又不是同步调用,就可以运用MQ到这个业务中。以电商应用为例,用户创建订单后,如果耦合调用 库存系统、物流系统、支付系统,任何一个子系统出了故障或者因为升级等原因暂时不可用,都会造成下单操作异常,影响用户使用体验。

(2)异步:这个很好理解,比如用户的操作日志的维护,可以不用同步处理,节约响应时间。

(3)削峰:在高峰期的时候,系统每秒的请求量达到 5000,那么调用 MySQL 的请求也是 5000,一般情况下 MySQL 的请求大概在 2000 左右, 那么在高峰期的时候,数据库就被打垮了,那系统就不可用了。此时引入MQ,在系统 A 前面加个 MQ,用户请求先到 MQ,系统 A 从 MQ 中每秒消费2000 条数据,这样就把本来 5000 的请求变为 MySQL 可以接受的请求数量了,可以保证系统不挂掉,可以继续提供服务。MQ 里的数据可以慢慢的把它消费掉。

2、使用了MQ会有什么问题?

(1)降低了系统可用性 :系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。

(2)增加了系统的复杂性:如何保证消息没有被重复消费?

3、为什么要用Rocketmq?

单机吞吐量:十万级;

可用性:非常高,分布式架构,多主多从;

消息可靠性:经过参数优化配置,消息可以做到0丢失

功能支持:MQ功能较为完善,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等。

支持10亿级别的消息堆积,不会因为堆积导致性能下降。

源码是java,比较容易做二次开发,进行定制。

在阿里双11已经经历了多次考验,稳定性好。

4、RocketMQ集群部署结构

1) Name Server

NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。

2) Broker

Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时(每隔30s)注册Topic信息到所有NameServer。NameServer定时(每隔10s)扫描所有存活broker的连接,如果NameServer超过2分钟没有收到心跳,则NameServer断开与Broker的连接。

3) Producer

Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。Producer每隔30s(由ClientConfig的pollNameServerInterval)从Nameserver获取所有topic队列的最新情况,这意味着如果Broker不可用,Producer最多30s能够感知,在此期间内发往Broker的所有消息都会失败。Producer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的broker发送心跳,Broker每隔10s中扫描所有存活的连接,如果Broker在2分钟内没有收到心跳数据,则关闭与Producer的连接。

4) Consumer

Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。Consumer每隔30s从NameServer获取topic的最新队列情况,这意味着Broker不可用时,Consumer最多最需要30s才能感知。Consumer每隔30s(由ClientConfig中heartbeatBrokerInterval决定)向所有关联的broker发送心跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送心跳数据,则关闭连接;并向该ConsumerGroup的所有Consumer发出通知,Group内的Consumer重新分配队列,然后继续消费。

5、零拷贝原理

Linux操作系统分为【用户态】和【内核态】,文件操作、网络操作需要涉及这两种形态的切换,免不了进行数据复制。一台服务器 把本机磁盘文件的内容发送到客户端,一般分为两个步骤: 1)read;读取本地文件内容;

2)write;将读取的内容通过网络发送出去。 这两个看似简单的操作,实际进行了4 次数据复制,分别是:

1. 从磁盘复制数据到内核态内存;

2. 从内核态内存复制到用户态内存;

3. 然后从用户态 内存复制到网络驱动的内核态内存;

4. 最后是从网络驱动的内核态内存复 制到网卡中进行传输。

通过使用mmap的方式,可以省去向用户态的内存复制,提高速度。这种机制在Java中是通过MappedByteBuffer实现的,RocketMQ充分利用了上述特性,也就是所谓的“零拷贝”技术,提高消息存盘和网络发送的速度。 这里需要注意的是,采用MappedByteBuffer这种内存映射的方式有几个限制,其中之一是一次只能映射1.5~2G 的文件至用户态的虚拟内存,这也是为何RocketMQ 默认设置单个CommitLog日志数据文件为1G的原因了

6、消息存储结构

RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成 的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,

类似数据库的索引文件,存储的是指向物理存储的地址。每个Topic下的每个Message Queue都有一个对应的ConsumeQueue文件。

CommitLog:存储消息的元数据

ConsumerQueue:存储消息在CommitLog的索引

IndexFile:为了消息查询提供了一种通过key或时间区间来查询消息的方法,这种通 过IndexFile来查找消息的方法不影响发送与消费消息的主流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值