浅析RocketMQ


前言

RocketMQ是阿里巴巴中间件团队自研的一款高性能、高吞吐量、低延迟、高可用、高可靠(具备金融级稳定性)的分布式消息中间件,开源后并于2016年捐赠给Apache社区孵化,目前已经成为了
Apache顶级项目。


一、特性

  1. 订阅与发布
    消息的发布是指某个生产者向某个topic发送消息;消息的订阅是指某个消费者关注了某个topic中带有某些tag的消息
  2. 消息顺序
    消息有序指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的。RocketMQ可以严格的保证消息有序
  3. 消息过滤
    RocketMQ的消费者可以根据Tag进行消息过滤,也支持自定义属性过滤。消息过滤目前是在Broker端实现的,优点是减少了对于Consumer无用消息的网络传输,缺点是增加了Broker的负担、而且实现相对复杂
  4. 消息可靠性
    RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:
    1)Broker非正常关闭
    2)Broker异常Crash
    3)OS Crash
    4)机器掉电,但是能立即恢复供电情况
    5)机器无法开机(可能是cpu、主板、内存等关键设备损坏)
    6)磁盘设备损坏
    1)、2)、3)、4) 四种情况都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。
    5)、6)属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。
    RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。
    通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。
  5. 至少一次
    至少一次(At least Once)指每个消息必须投递一次。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性
  6. 回溯消费
    回溯消费是指Consumer已经消费成功的消息,由于业务上需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费一般是按照时间维度,例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按
    照时间维度来回退消费进度。RocketMQ支持按照时间回溯消费,时间维度精确到毫秒
  7. 事务消息
    RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。
    RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的
    最终一致性
  8. 定时消息
    定时消息(延迟队列)是指消息发送到broker后,不会立即被消费,等待特定时间投递给真正的
    topic。
    broker有配置项messageDelayLevel,默认值为“1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m
    9m 10m 20m 30m 1h 2h”,18个level。
    messageDelayLevel是broker的属性,不属于某个topic。发消息时,设置delayLevel等级即可:
    msg.setDelayLevel(level)。level有以下三种情况:
    level == 0,消息为非延迟消息
    1<=level<=maxLevel,消息延迟特定时间,例如level1,延迟1s
    level > maxLevel,则level
    maxLevel,例如level==20,延迟2h
    定时消息会暂存在名为SCHEDULE_TOPIC_XXXX的topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟
    的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。
    需要注意的是,定时消息会在第一次写入和调度写入真实topic时都会计数,因此发送数量、tps都会变高
  9. 消息重试
    Consumer消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer消费消息失败
    通常可以认为有以下几种情况:
    1)由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的
    手机号被注销,无法充值)等。这种错误通常需要跳过这条消息,再消费其它消息,而这条失败的消息
    即使立刻重试消费,99%也不成功,所以最好提供一种定时重试机制,即过10秒后再重试。
    2)由于依赖的下游应用服务不可用,例如db连接不可用,外系统网络不可达等。遇到这种错误,即
    使跳过当前失败的消息,消费其他消息同样也会报错。这种情况建议应用sleep 30s,再消费下一条消
    息,这样可以减轻Broker重试消息的压力

二、高级特性

1.高可用机制

RocketMQ分布式集群是通过Master和Slave的配合达到高可用性的。
Master和Slave的区别:

  1. 在Broker的配置文件中,参数brokerId的值为0表明这个Broker是Master,
  2. 大于0表明这个Broker是Slave,
  3. brokerRole参数也说明这个Broker是Master还是Slave。
    (SYNC_MASTER/ASYNC_MASTER/SALVE)
  4. Master角色的Broker支持读和写,Slave角色的Broker仅支持读。
  5. Consumer可以连接Master角色的Broker,也可以连接Slave角色的Broker来读取消息。

2.刷盘机制

RocketMQ 的所有消息都是持久化的,先写入系统 PageCache,然后刷盘,可以保证内存与磁盘都有一份数据, 访问时,直接从内存读取。消息在通过Producer写入RocketMQ的时候,有两种写磁盘方式,分布式同步刷盘和异步刷盘

3.负载均衡

分页模式(随机分配模式)

• 手动配置模式

• 指定机房模式

• 就近机房模式

• 统一哈希模式

• 环型模式

4.死信队列

RocketMQ中消息重试超过一定次数后(默认16次)就会被放到死信队列中,在消息队列
RocketMQ 中,这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),存储死信
消息的特殊队列称为死信队列(Dead-Letter Queue)。可以在控制台Topic列表中看到“DLQ”相关的
Topic,默认命名是:
%RETRY%消费组名称(重试Topic)
%DLQ%消费组名称(死信Topic)
死信队列也可以被订阅和消费,并且也会过期

死信消息具有以下特性:

  • 不会再被消费者正常消费。
  • 有效期与正常消息相同,均为 3 天,3 天后会被自动删除。因此,请在死信消息产生后的 3
    天内及时处理。
    死信队列具有以下特性:
  • 一个死信队列对应一个 Group ID, 而不是对应单个消费者实例。
  • 如果一个 Group ID 未产生死信消息,消息队列 RocketMQ 不会为其创建相应的死信队列。
    一个死信队列包含了对应 Group ID 产生的所有死信消息,不论该消息属于哪个 Topic。

总结

RocketMQ备受金融公司青睐,学习他也将是面试神器。如果你不想吃生活的苦,就跟我一起吃学习的苦吧,我是油条~下期见!

ThreadLocal 是 Java 中的一个类,它提供了一种线程局部变量的机制。线程局部变量是指每个线程都有自己的变量副本,每个线程对该变量的访问都是独立的,互不影响。 ThreadLocal 主要用于解决多线程并发访问共享变量时的线程安全问题。在多线程环境下,如果多个线程共同访问同一个变量,可能会出现竞争条件,导致数据不一致或者出现线程安全问题。通过使用 ThreadLocal,可以为每个线程提供独立的副本,从而避免了线程安全问题。 ThreadLocal 的工作原理是,每个 Thread 对象内部都维护了一个 ThreadLocalMap 对象,ThreadLocalMap 是一个 key-value 结构,其中 key 是 ThreadLocal 对象,value 是该线程对应的变量副本。当访问 ThreadLocal 的 get() 方法时,会根据当前线程获取到对应的 ThreadLocalMap 对象,并从中查找到与 ThreadLocal 对象对应的值。如果当前线程尚未设置该 ThreadLocal 对象的值,则会通过 initialValue() 方法初始化一个值,并将其存入 ThreadLocalMap 中。当访问 ThreadLocal 的 set() 方法时,会将指定的值存入当前线程对应的 ThreadLocalMap 中。 需要注意的是,ThreadLocal 并不能解决共享资源的并发访问问题,它只是提供了一种线程内部的隔离机制。在使用 ThreadLocal 时,需要注意合理地使用,避免出现内存泄漏或者数据不一致的情况。另外,由于 ThreadLocal 使用了线程的 ThreadLocalMap,因此在使用完 ThreadLocal 后,需要手动调用 remove() 方法清理对应的变量副本,以防止内存泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值