概述

消息的有序性指的是一个生产者生产的消息消费顺序和生产顺序一致,例如使用binlog+mq进行数据同步的时候,对于单条记录的增加、和修改和删除应该保持有序,消费消息时如果消息变成删除、修改和删除,则导致同步数据不一致。对于最简单的消息模型,一个生产者+一个消息队列+一个消费者,由于队列具有先进先出(FIFO,first in first out)特性,这样的消息模型消息时有序的。

消息从生产到消费有两个传输阶段,第一个阶段是从生产者到消息队列,第二个节点是从消息队列推送到消费端,为了使用保证消息MQ中消息有序,需要在两阶段进行控制。

实例

比如通过mysql binlog进行两个数据库的数据同步,由于对数据库的数据操作是具有顺序性的,如果操作顺序搞反,就会造成不可估量的错误。比如数据库对一条数据依次进行了 插入->更新->删除操作,这个顺序必须是这样,如果在同步过程中,消息的顺序变成了删除->插入->更新,那么原本应该被删除的数据,就没有被删除,造成数据的不一致问题。

实例一

问题描述

一个queue,有多个consumer去消费,这样就会造成顺序的错误,consumerMQ里面读取数据是有序的,但是每个consumer的执行时间是不固定的,无法保证先读到消息的consumer一定先完成操作,这样就会出现消息并没有按照顺序执行,造成数据顺序错误。

image-20230220232418757

解决措施

拆分成多个queue,每个queue一个consumer,就是多一些queue而已,确实是麻烦点;这样也会造成吞吐量下降,可以在消费者内部采用多线程的方式去消费。

image-20230220232728481

实例二

问题描述

一个queue对应一个consumer,但是consumer里面进行了多线程消费,这样也会造成消息消费顺序错误。

image-20230220232536050

解决措施

或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理。

image-20230220232805362

其他的解决措施

因为是对同一个数据进行操作,那么可以使用信号量来标识当前数据的状态,例如在初始化时,数据为0,删除时将状态由0改为1,插入操作时由1改为2,执行更新操作时,需要将状态由2改为3。每一步操作都会判断当前数据的状态和id,id匹配进行操作,状态符合,进行下修改。