RocketMQ深入浅出
RocketMQ的高可用和负载均衡机制
RocketMQ采用了主从复制(Master-Slave Replication)的方式来实现Broker的高可用。每个Broker可以配置一个或多个Slave,与Master同步消息。Master和Slave之间采用异步复制的方式,即Master在收到消息后立即返回给Producer,然后将消息发送给Slave。这样可以提高性能,但也存在一定的数据丢失风险。为了降低风险,RocketMQ提供了两种消息级别:可靠同步双写(RELIABLE_SYNC_DUAL_WRITE)和可靠异步双写(RELIABLE_ASYNC_DUAL_WRITE)。可靠同步双写是指Master在收到消息后,等待Slave确认接收后再返回给Producer。可靠异步双写是指Master在收到消息后,立即返回给Producer,然后等待Slave确认接收后再删除内存中的消息。
RocketMQ采用了一种基于权重的负载均衡算法(Weighted Round-Robin Scheduling)来实现Producer和Consumer之间的负载均衡。每个Producer或Consumer会根据自己的性能和负载情况,向NameServer报告自己的权重值。NameServer会根据权重值,为每个Topic分配一个Message Queue列表,并按照权重值的比例,将列表分配给各个Producer或Consumer。Producer或Consumer会根据分配到的列表,轮询地向不同的Broker发送或拉取消息。
RocketMQ的事务消息和延迟消息机制
RocketMQ支持两种特殊类型的消息:事务消息(Transaction Message)和延迟消息(Delay Message)。
事务消息是指在分布式事务中使用的消息,可以保证消息的最终一致性。事务消息有三种状态:提交状态(Commit State)、回滚状态(Rollback State)和未知状态(Unknown State)。事务消息的发送流程如下:
- Producer发送一条预备状态(Prepared State)的事务消息到Broker,并开始执行本地事务。
- Broker收到预备状态的事务消息后,暂时不可见,等待Producer的确认。
- Producer执行本地事务后,根据执行结果向Broker发送提交或回滚的指令。
- Broker根据Producer的指令,将事务消息转换为提交状态或回滚状态。提交状态的事务消息变为可见,可以被消费;回滚状态的事务消息被删除,不可被消费。
如果Producer在执行本地事务过程中宕机或者超时,Broker无法收到Producer的指令,此时事务消息处于未知状态。为了解决这个问题,Broker会定期扫描未知状态的事务消息,并向Producer发起回查请求。Producer收到回查请求后,会检查本地事务的状态,并重新向Broker发送提交或回滚的指令。
延迟消息是指在指定时间后才能被消费的消息,可以用于实现定时任务或者延时重试等功能。延迟消息的实现原理如下:
- Producer发送一条延迟级别(Delay Level)的延迟消息到Broker。延迟级别是一个预定义好的时间参数,例如1s、5s、10s等。
- Broker收到延迟消息后,根据延迟级别将消息存储到对应的延迟队列(Delay Queue)中。延迟队列是一种特殊类型的队列,用于暂存延迟消息。
- Broker定期扫描延迟队列中的消息,如果发现某条消息已经达到或超过了延迟时间,则将该消息转移到对应的主题队列(Topic Queue)中。
- Consumer从主题队列中拉取或推送消息,并进行消费。
RocketMQ的消息存储机制是基于JDK NIO的内存映射机制(MappedByteBuffer)的,消息存储时首先将消息追加到内存,再根据配置的刷盘策略在不同时间进行刷写磁盘。RocketMQ的消息存储结构主要包括CommitLog、ConsumeQueue和IndexFile三部分。CommitLog是Broker存储消息的物理文件,采用顺序写入的方式提高性能。ConsumeQueue是Broker为每个Message Queue建立的一个索引文件,用于存储该队列中每条消息在CommitLog中的位置信息。IndexFile是Broker为每个Topic建立的一个索引文件,用于根据消息的Key或者时间区间查询消息¹⁶。RocketMQ支持两种持久化策略:同步刷盘(SYNC_FLUSH)和异步刷盘(ASYNC_FLUSH)。同步刷盘是指在返回给Producer之前,将消息写入磁盘并刷新。异步刷盘是指在返回给Producer之前,将消息写入内存缓冲区,并定时刷新到磁盘。