消息生产
- 消息压缩:将较大的消息进行压缩后发送到服务端,有效利用带宽。
- 延迟消息:设计消费时延,消息发送到服务端后,过了预设时间才可以被消费。
- 事务消息:根据预设的事务,事务消息可保证分布式系统之间的数据最终一致。
消息消费
- 有序消费:支持普通有序消息和严格有序消息两种方式。
- 集群消费:一个主题可被一个或多个消费者组消费,消费者组中消费者实例可平均分摊消费信息。
- 消费位置设置:支持设置消费组首次启动消费的位置,包括队列头、队列尾及由客户端指定。
- 消息回溯:支持按时间回溯消费进度,将订阅组在某主题上的消费进度重置到过去或者未来。
完善的运维能力
- 应用用户管理:集群租户隔离,应用接入集群权限管理。
- 主题管理:支持对实例下的主题进行管理,执行创建删除等操作。
- 订阅组管理:支持对实例下的订阅组进行管理。
- 生产者和消费者管理:用户可查看当前实例下的生产者和消费者信息,并实时更新。
- 消息查询:按消息ID、消息逻辑偏移量、消息key。
- 完善的运维功能,节点状态检测、启停;实例状态检测、启停;SLA监控等。
顺序消息
顺序消息是指消费消息的顺序要同发送消息的顺序一致,在 RocketMQ 中,主要有两种有序消息:全局有序消息和局部有序消息(又称普通有序消息、分区有序消息)。
普通有序消息:在正常情况下可以保证完全的顺序消息,但是一旦发生通信异常造成Broker 重启,队列总数发生变化,哈希取模后定位的队列会变化,因此会产生短暂的消息顺序不一致。如果业务能容忍在集群异常情况(如某个 Broker 宕机或者重启)下消息短暂的乱序,使用普通顺序方式比较合适。
严格有序消息:无论正常异常情况都能保证顺序,但是牺牲了分布式Failover 特性,即 Broker 集群中只要有一台机器不可用,则整个集群都不可用(或者影响hash 值对应队列的使用),服务可用性大大降低。如果服务器部署为同步双写模式,此缺陷可通过备机自动切换为主避免,不过仍然会存在几分钟的服务不可用。
事务消息
消息队列 RocketMQ 提供类似 X/Open XA 的分布事务功能。半事务消息发送后,根据预设的事务进行判断,满足事务的消息将会被服务端确认,不满足的事务的消息不会被服务端接收,从而实现在分布式场景下保障消息生产和本地事务的最终一致性。
半消息: 暂不能投递的消息,发送方已经将消息成功发送到了消息队列服务端,但是服务端未收到生产者对该消息的二次确认,此时该消息被标记成“暂不能投递”状态,处于该种状态下的消息即半消息。
消息回查: 由于网络闪断、生产者应用重启等原因,导致某条事务消息的二次确认丢失,消息队列 RocketMQ服务端通过扫描发现某条消息长期处于“半消息”时,需要主动向消息生产者询问该消息的最终状态(Commit 或是 Rollback),该过程即消息回查。
延时消息
生产者将消息发送到消息队列RocketMQ服务端,设计消费时延,在预设的时间后才可以被消费者消费。发送延时消息时需要设定一个延时时间长度,消息将从当前发送时间点开始延迟固定时间之后才开始投递,实现分布式场景的延时调度触发效果。
广播消费/集群消费
广播消费:在广播消费模式下,一条消息被多个Consumer消费,即使这些Consumer属于同一个ConsumerGroup,消息也会被ConsumerGroup中的每个Consumer都消费一次,广播消费中的ConsumerGroup 概念可以认为在消息划分方面无意义。
集群消费:一个Topic可以被一个或多个ConsumerGroup消费,每个ConsumerGroup有自己独立的消费进度,消费进度是保存在服务端的。 一个ConsumerGroup中的消费者实例可以平均分摊消费消息,做到负载均衡。例如某个Topic有9条消息,其中一个ConsumerGroup有3个不同的消费者实例(可能是3个进程,或者3台机器),那么每个实例只消费其中的3条消息。在此消费模式下,可以做到Point-To-Point的消费,也可以做到JMS里面广播消费,能满足绝大部分场景,推荐使用此消费模式。
消息重试
对于有序消息:有序消息不能跳跃签收,当消费者消费消息失败后,消息队列RocketMQ会自动不断进行消息重试 (每次间隔时间为1秒),此时应用会出现消息消费被阻塞的情况。因此建议使用有序消息时,务必保证应用能够及时监控并处理消费失败的情况,避免阻塞现象的发生。
对于无序消息:消息队列RocketMQ默认允许每条消息最多重试16次。
每次重试的间隔时间如下:
第几次重试 | 与上次重试的间隔时间 |
---|---|
1 | 10秒 |
2 | 30秒 |
3 | 1分钟 |
4 | 2分钟 |
5 | 3分钟 |
6 | 4分钟 |
7 | 5分钟 |
8 | 6分钟 |
9 | 7分钟 |
10 | 8分钟 |
11 | 9分钟 |
12 | 10分钟 |
13 | 20分钟 |
14 | 30分钟 |
15 | 1小时 |
16 | 2小时 |
如果消息重试16次后仍然失败,消息将不再投递。如果严格按照上述重试时间间隔计算,某条消息在一直消费失败的前提下,将会在接下来的4小时46分钟之内进行16次重试,超过这个时间范围消息将不再重试投递。
消息过滤
消费者订阅了某个Topic后,消息队列RocketMQ会将该主题中的所有消息投递给消费者。若消费者只需要关注部分消息,可通过设置过滤条件在消息队列RocketMQ版服务端进行过滤,只获取到需要关注的消息子集,避免接收到大量无效的消息。
消息过滤主要通过以下几个关键流程实现:
- 生产者:生产者在初始化消息时预先为消息设置一些属性和标签,用于后续消费时指定过滤目标。
- 消费者:消费者在初始化及后续消费流程中向服务端上报需要订阅指定主题的哪些消息,即过滤条件。
- 服务端:消息队列RocketMQ服务端根据消费者上报的过滤条件的表达式进行匹配,将符合条件的消息投递给消费者进行消费。
消息队列RocketMQ支持两种过滤方式:
- 通过Tag进行过滤:生产者在发送消息时,设置消息的Tag标签,消费者通过 Tag标签指定需要消费的信息。
- 通过SQL属性过滤:通过生产者为消息设置的属性(Key)及属性值(Value)进行匹配。生产者在发送消息时可设置多个属性,消费者订阅时可设置SQL语法的过滤表达式过滤多个属性。