文章目录
一、rocketmq作用
流量削峰:延时消费
数据采集:日志等数据的采集
异步解耦:系统之间解耦
二、rocketmq工作原理
消息的生产
路由表:实际是一个map,Key为topic名称,value是一个QueueData列表。简单说,路由表的key为topic名称,value为所有涉及该topic的BrokerName列表。
三、rocketmq的应用
发送消息
发送消息的三种方式
同步发送
异步发送
需要指定一个回调函数
单向发送:只发不收,效率最高,可靠性差
消息发送的四种状态
SEND_OK 发送成功
FLUSH_DISK_TIMEOUT 刷盘超时 刷盘策略为同步才会出现
FLUSH_SLAVE_TIMEOUT 主从同步超时 master-slave模式下才会出现
SLAVE_NOT_AVAILABLE 没有可用的从机 master-slave模式下才会出现
消费消息
消息消费者举例
消息消费的方式
广播模式
所有consumer都消费全部的消息
集群模式
每个consumer只消费自己需要的消息(默认模式)
顺序消费
问题描述
默认情况下,生产者会把消息以RoundRobin轮询方式发送到不同的queue分区队列;而消费消息时会从多个queue上拉取消息,这种情况下,生产和消费的顺序就得不到保证了。如果只将消息生产到一个队列,然后消费也只从一个队列取消息消费,则可以保证顺序。
有序分类
全局有序
当发送和消费参与的queue只有一个时,保证的有序是整个topic的有序,称为全局有序。
也就是一个topic只有一个queue。
分区有序
如果有多个queue参与,其仅可保证在该分区队列queue上的有序性,称为分区有序。
如何实现queue的选择
在定义Producer时我们可以指定消息队列选择器,而这个选择器是我们自己实现了MessageQueueSelector接口定义的。
在定义选择器的选择算法时,一般需要使用选择key。这个选择key可以是消息key,也可以是其他数据,但必须是唯一的。
一般性的选择算法是,让选择key(或其hash值)与该topic所包含的queue数量取模,其结果即为选择的Queue的QueueId。 一般性的作法是,从消息中获取到选择key,对其进行判断,若是当前Consumer需要消费的消息,则消费,不是则不做处理。
不属于那个Consumer的消息被拉取走了,那么应该消费这条消息的Consumer还能否拿到这条消息吗?同一个Queue中的消息,不可能被同一个Group中的不同Consumer消费。所以消费同一个Queue的不同选择key的消息的Consumer一定属于不同的Group,而不同的Group中的Consumer之间的消费是相互隔离的,互不影响的。
示例
producer:
rocketmq如何保证有序总结
首先单个分区(queue)是有序的,但多个分区,就无法保证consumer能顺序去取消息消费。此时需要在生产者的生产消息上加一个选择器selector,(此处举例订单号)对订单号取模投放分区,就能保证同一个订单的相关消息都投送到同一个分区,同一个分区的消息是有序的,所以此时consumer去消费就是有序的了。
如果consumer是集群分布的,那么就会有多个一样的consumer去消费同一个分区,此时就需要对分区加锁,来保证同时只能有一个consumer进入分区消费。
延时消费
概念
当消息写入到broker后,在经过指定时长后才会被消费的消息,称为延时消息。
采用rocketMQ的延时消息实现定时任务的功能,而无需使用定时器。典型的应用场景是,电商交易中超时未支付关闭的场景,12306订单超时未支付取消订票的场景。
在电商平台中,订单创建会发送一条延时消息,在30分钟后去后台业务系统(consumer),如果该条订单已经关闭,则不做处理;如果未关闭(未完成支付),则商品返回库存,关闭订单。
延时等级
延时消息的延时时长并不支持任意时长的延迟,而是按照等级划分的。延时等级定义在rocketMQ服务端的MessageStoreConfig类中。
即延时等级为1代表1s,延时等级为3代表10s