RocketMQ模型和生产实践
代理者位点:表示消息存储到多少号了,消费者位点:表示消费者消费到哪条消息了,消费到哪个点了。差值就是剩余还没有消费的。如果差值越来越大,就可能会有丢消息的可能。
注意:上面三个值都是broker来维护的。
消费者一定要给broker返回一个值,让broker去决定这条消息是否还要继续进行发送。
顺序消息机制
RocketMQ的消费者接收消息的顺序可能会和生产者发送消息的顺序不一致,但是其保证的是局部的一组消息的一致性;保证的是局部的有序性,大部分情况下,我们说的保证有序性是保证的局部有序性。
有序,就是生产者要保证发送到同一个队列messageQueue中,可以通过取余等机制,保证相同的一组信息发送到同一个queue中;
又因为queue就能自己保证有序性,就能保证消息的顺序传递,先进先出。
然后还有一点就是消费者方也要进行处理,保证顺序消费;使用不同的监听器,使用MessageListenerOrderly这个监听器。又因为为了保证吞吐量,拉取消息的时候是多个线程去并发拉取?消费者拉取消息的时候是每次拉32条,从哪里拉的不确定,随意,这样就可能会导致无序。多线程情况下就无法保证有序性了。
为了保证有序性,先锁定一个队列,将这个队列的消息消费完毕之后,才会去切换到别的队列进行处理。这个是不同的模型。
如果失败了,就阻塞当前队列一会儿,为了保证顺序性,就会阻塞整个队列,等到处理成功了才会解除这个阻塞。顺序消息对吞吐量有影响的。
如果是并发处理模型,中间一个处理失败了,可能会去后面继续消费,只要保证本次拿到32条消息能够消费就可以了。
一般都是保证局部有序就行了。要全局有序的话,所有的消息都要放到同一个messageQueue,这样就没有分布式的优势了。
顺序消费,消费者拉取的时候锁定一个队列,也是可以使用多线程线程池去并发拉取这个队列中的消息,但是需要消费者本身进行控制,保证有序性。
延迟消息:
批量消息
可以减少IO的消耗,放到一个list中;减少了IO次数,如果网络异常,那么消息就丢失了;有限制,大小不超过1M,这个限制不是强制性的。消息进行分割,分成几个批次,进行请求。
批量发,减少IO,然后要考虑安全性,每次消息大小不能太大,可以对消息进行压缩成二进制,消费者再解压等等。RocketMQ已经进行了一些压缩。
批量发送就是尽量减少请求次数,可以使用spilt进行拆分一下。
针对边缘的优化。这才是RocketMQ的精髓。
过滤消息
消费者组中多个消费者进行协作,一般情况下是不可控的,为了保证可控;就可以用到消息过滤机制。发送消息的时候生产者可以指定tag,消费者同样也订阅这个tag。subscribe这个方法订阅指定的tag,多个tag使用 || 隔开。订阅的时候订阅指定的tag,过滤是在哪里?一个是broker端,这样发送到消费者的就少了;还有就是在消费者端进行过滤,全部接收,但是进行过滤的消费。
broker端处理:网络压力小了,但是其本身的压力就大了。这里面是要有取舍的。
RocketMQ优先保证的是网络的性能,也就是在broker端实现的。不建议定义很复杂的订阅条件。
如果是更复杂的过滤条件,生产者发送的时候还是正常发送带tag的消息;然后在消费者端定义MessageSelector.bySql。
默认情况下,服务端broker不支持bySql的方式。在集群中有一个配置可以进行配置,enablePropertyFilter,通过这个进行配置。默认值是false。修改为true。修改之后broker才支持bySql。为了防止broker端更繁忙。
典型的流式处理方式:先拿一个应用来过滤,然后通过topic来发送,保证每个messageQueue使用同一个方式去消费;这样的方式要明显高于broker端进行sql过滤。
事务消息:
重点,非常重点。
写本地事务,和发消息如果不控制,就会出现不一致;提供一个机制,保证这两个是同步的。完整的业务场景下,上游客户下单,下游商家发货,这才是完整的事务。但是在分布式情况下,这个链路太长了。RocketMQ进行了折中处理,只保证前面一半保证原子性。后面从broker到消费者的这个过程,事务可以由消费者来控制,自己确认,同步进行返回消息消费状态。
这并不是标准的分布式解决方案。是半事务。后面的一半由消费者自己去实现。
RocketMQ的事务消息和消费者无关,只是和生产者和broker相关。producer.setTransactionListener().
所谓半消息half消息,是生产者发送这个半消息,然后broker将其挪到内部的一个topic中,该topic是RMQ_SYS_TRANS_HALF_TOPIC。如果确认成功,broker将这个消息从这个topic中挪出来,发到消费者订阅的topic中。
返回unknown状态,broker就要进行回查;多久回查一次,回查多少次这些是要配置的。本地事务回查次数通过参数transactionCheckMax设定,默认15次。本地事务回查的间隔通过参数transactionCheckInterval设定,默认60秒。超过回查次数后,消息将会被丢弃。
定时任务,例如买票订单确认,15分钟未支付就取消订单,支付了就分配座位。如果使用定时任务,15分钟后去执行,那么如果是15分钟内支付了,但是不能马上去分配位置,必须要等定时任务启动才行,这样当然是不行的。也不符合业务逻辑。这个场景是broker级别配置的,配置完成之后这个broker中的所有message Queue都会生效。
messageQueue一般建议配置是broker数量的两倍。broker中一个topic的messageQueue数量默认是8个,也可以自动进行确认。
RocketMQ如果启动了长时间,那么从控制台可能会看到消息的最小位点就不是0了,因为日志文件默认是1G,超过之后就写一个新的文件;历史文件默认保存120个小时,凌晨4点会删除过期的文件,删除之后历史的消息就找不到了。清空了。
消费模型:消费者组中的消费者可以消费一个broker中的一个messageQueue,也可以消费多个messageQueue,也可以跨broker消费messageQueue;但是broker中的messageQueue只会被消费者组中的一个消费者去消费,不会出现一个messageQueue被一个消费者组中的多个消费者消费。
权限控制
非核心功能,一般来说MQ是内部使用的,根本就无序进行权限控制,但是RocketMQ提供了权限控制的功能。perm,6可读可写;4是可读不可写;2禁写禁读。太粗粒度了。
幂等
对消费者来说,不保证只推送一次,保证最少一次;可以向同一个消费者推送多次,或者可以向不同的消费者推送。
RocketMQ提供messageId,这个不靠谱,事务消息,或者多次转发的过程中,这个可能会变;建议自己去实现这个消息id。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战