一 场景
存在两个系统A系统和B系统,A系统的数据要同步到B系统,数据量比较大而且不需要即时的反馈,所以使用消息队列进行数据的同步,同步的数据包括单据数据及单据关联的费用数据,由于费用数据的处理和单据数据的处理不在一个操作,所以需要保证消息的顺序性
二 分析
- 如何保证消息的顺序性,我们知道队列可以保证消息的顺序性,所以同一条单据数据,和其对应的单据费用放到同一个队列就可以了
三 解决
通过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的顺序消费