使用RabbitMq保证顺序消费

3,131 阅读1分钟

一 场景

存在两个系统A系统和B系统,A系统的数据要同步到B系统,数据量比较大而且不需要即时的反馈,所以使用消息队列进行数据的同步,同步的数据包括单据数据及单据关联的费用数据,由于费用数据的处理和单据数据的处理不在一个操作,所以需要保证消息的顺序性

二 分析

  1. 如何保证消息的顺序性,我们知道队列可以保证消息的顺序性,所以同一条单据数据,和其对应的单据费用放到同一个队列就可以了

三 解决

通过getMqRoutingKey方法,根据传入的单据id取模,为相同的单据id数据走相同的routingkey,而routingkey和对列是1对1的,所以就保证了相同的单据id走同一个队列

```
public static String ROUT_KEY_A = "uans.agency.A";

public static String ROUT_KEY_B = "uans.agency.B";

public static String ROUT_KEY_C = "uans.ageny.C";

public static String ROUT_KEY_D = "uans.agency.D";

public static String ROUT_KEY_E = "uans.agency.E";


public static String[] ROUTING_KEY_ARRAY = {ROUT_KEY_A, ROUT_KEY_B, ROUT_KEY_C,
        ROUT_KEY_D, ROUT_KEY_E};

public static String getMqRoutingKey(String manifestId) {
    int hashCode = Math.abs(manifestId.hashCode()) % ROUTING_KEY_ARRAY.length;
    return ROUTING_KEY_ARRAY[hashCode];
}
```

这里会发现一个问题,就是走了取模处理,这么做的原因是如果把所有单据数据都放入到一个队列中,队列的数据量大会导致性能问题。

发送消息到服务端

public void sendDataMessageToMQ(String manifestId,
                                Map<String, Object> header,
                                Object content) {
    CorrelationData correlationData = getCorrelationData();
    this.sendMsg(MQConstant.getMqRoutingKey(manifestId), header, content, correlationData);
    logger.info("发送消息成功correlationId:{}", correlationData.getId());
}

在服务端为routingKey绑定队列。

这样就实现了RabbitMq的顺序消费