MQ使用心得

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MQ使用心得相关的知识,希望对你有一定的参考价值。

首先简述一下我的业务场景:A系统将需要同步到第三方的报文发送到MQ,同步系统消费MQ做同步;相当于将系统业务与同步独立拆分;

1.前期调研

技术调研: 技术这块前期对比了开源的几种MQ的优缺点,不过公司有自己的MQ平台,所以就采用的公司的MQ;
业务调研: 虽然只是做同步,为什么要用到MQ呢?rest接口它不香吗?是这样的,在做同步的时候,需要保证顺序,比如说:A报文与B报文之间,必须A报文先同步成功之后,B报文才可以同步;否则第三方系统那边会造成数据异常;

2.方案1-基于数据库

业务系统侧,将需要同步的报文都保存到一张表里面,设置状态为未同步;然后同步平台读取表中未同步的报文,按报文的创建时间排序后,依次同步;
起初就是这么设计的,在不断的去摸索之后,发现有些问题:

1.同步平台是多节点部署,如何去保证同步表中的一条报文不会被同步多次?

技术图片
这个问题是可以解决的:通过version或者redis分布式锁;

2.如何保证报文顺序?

假如现在报文为:
3 {报文}
2 {报文}
1 {报文}
如果server1同步id=3的报文,server2同步id=2的报文;此时,server2先同步成功,server3再同步成功的时候,第三方服务一样会导致数据错误;
技术图片
看似可以解决,但是如果新增一台server就会相对比较麻烦;

3.方案2-基于MQ

技术图片
MQ是会存在重复消费的行为,所以需要在消费端做消息的幂等性,如果添加server节点,只需要在hash时,分发到不同的queue就可以;
每个queue代表一种业务类型,每种业务类型之间保证同步顺序,如果需要使用全局顺序的消息,则需要使用topic来完成;

看似完美的解决方案,其实还有问题:

1.如果消息在消费端处理的过程中,突然停服了,这条消息肯定不会在MQ中丢失,因为MQ没有收到成功响应,但是,下次服务启动时,消费此条消息时,幂等性会将此消息拦截掉,导致消息丢失;

解决思路:保存每条消息到数据库,并设置状态为消费中,当服务启动时,通过一台server(为什么是一台,因为如果是多台的话,会存在server1检测到server2在处理正常消费中的消息)来检查数据表中是否有消费中的记录,如果有,则先处理消费中的记录,处理完成后,再开始server1,server2的正常消费;

2.server1消费的比较慢,server1消费v3时,server2消费v6,v2?

技术图片

如果你消费消息之后的逻辑比较简单,可能会出现上述问题,一样没有保证消息的顺序性;
出现这种问题可以增加你的queue队列个数,因为消费消息时,是通过轮询的方式来消费不同的queue,queue个数增加了,也提高了每个队列的循环时间;
当然如果这样还解决不了,那你可以每台server对应一个topic来处理;

以上是关于MQ使用心得的主要内容,如果未能解决你的问题,请参考以下文章

Amazon AWS 使用心得(摸索篇一)

bpmn使用心得

Golang的pprof的使用心得(CPU,Heap)

消息队列知识点总结

ThinkPHP使用心得分享-分页类Page的用法

ThinkPHP使用心得分享-分页类Page的用法