各位,
我们团队在可靠MQ的设计上,出现了一些分歧性的意见,想拿出来和大家讨论讨论:
1,消息的可靠性设计,目前有2种模式:模式1是采用Notify的方式,先发送半消息,业务操作成功后最后提交完整消息,同时提供业务操作的检查接口,这种模式实现消息的最终一致性;模式2将业务数据和消息数据先都存在业务数据库里面,通过数据库的事务保证一致性,随后将消息转发给MQ。模式1的缺点是业务侵入性高,方案比较复杂,需要重新实现;模式2的缺点是消息数据可能会散落在各个地方,包括业务系统,而且可以集成现有MQ。
2,消息去重设计,也有2种模式:模式1是消费者根据自己的业务实现去重,模式2是在消费者端增加一个数据库表专门记录已经消费过的消息,不需要消费者根据业务去做去重。
不知道大家怎么看?
看Notify这个词我就知道又是蛋疼的淘系同学。
方案1、各种Check让人很蛋疼,但如果内部是需要垮库事务、分布式调用的场景的,我还真离不开他。让我可以在Check接口中回滚垮库、冲正其他系统的数据。
方案2、简单,非常适合事务都集中在一个库上的业务系统。后端挂上精卫拉binlog还是杠杠的,而且还和业务数据保持一个事务,清爽!
所以,两个我都要。done。
支持模式2 :D
说实在的,2个方案我都没有看懂,但就我的观点提供一点建议。
问题1,可靠性设计,这个问题如果转换一下,假设你问的不是MQ,而是数据库,就成了“数据库的可靠性设计”,如果你是在开发一个数据库,那是一个严肃的问题,如果你是在使用数据库,那可能是搞错方向了,换成“怎么使用事务保证数据的可靠性”之类的,可能更确切。MQ产品,据我所知,其本身而言,和数据库一样,对交给它的消息也需要提供可靠性保证,当然如果你把MQ的消息存储配成存在内存中,或不用事务提交,那就不保证了,就像你操作数据库的时候不用事务一样。
问题2,去重,据我所知,MQ除了要保证一条消息一定要送达外(即问题1),还要保证只被消费一次(当然,如果你愿意,也可以消费多次),如果你说的去重是指一条消息可能会被收到多次(从你的方案2推测的),那应该先好好了解一下MQ;如果是指业务上本身就会有重复内容的消息,那当然只能在业务上去处理了,就像数据库里,你可以主键都不要,插入内容完全相同的数据行,至于能不能重复,或重复的怎么处理,那完全上业务上的问题了。
在MQ环境里,一条消息无非是经过:生产(发送)、存储转发、消费(接收)三个环节,MQ在每个环节都需要提供可靠性保证,如向MQ发送一条消息,那到底有没有发出去,要有明确的回馈,就像向数据库里插入一条记录,到底有没有插进去,必须通过事务的成功或失败明确的回馈给客户端,这样的可靠性保证,应该通过数据库、MQ自身的机制来实现,而不能转移的应该层面。存储转发就不用说了,肯定不能一条消息莫名其妙的消失掉,也不能凭空多出消息来。消费的时候也是一样,一条消息到底有没有被消费掉,也是通过事务机制来控制的,不可能一条消息被消费掉了,下次去取又来了,不然这个MQ产品就是不可用的(当然你不发送ACK,故意让它留在broker上除外)