根据公司项目的一个使用场景,针对实时预警任务,会有同时消费某个设备正常或异常的事件,而这类事件具有时间维度上的先后性,需要符合先进先出(FIFO)原则进行发布和消费,而MQ消费为了吞吐量基本会使用多线程消费,RocketMQ也会分为多个消息队列,会造成消费无序的情况,这时候为了综合兼顾顺序消费+性能的考虑,可以使用分区顺序消息的策略。
生产顺序性
发送时将Sharding Key相同(例如同一设备)的消息路由到一个队列中。这样保证同一队列中消息的时序性。
部分代码参考如下:
asyncSendOrderly方法中的hashKey就是选择队列
@param hashKey use this key to select queue. for example: orderId, productId ...
java
@Resource
private RocketMQTemplate rocketMQTemplate;
rocketMQTemplate.asyncSendOrderly(destination, msg, deviceStatusInfoDTO.getDeviceId() + ":" + deviceStatusInfoDTO.getDeviceUniqueCode() + ":" + deviceStatusInfoDTO.getShopCode(), new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
}
@Override
public void onException(Throwable e) {
}
});
消费顺序性
顺序消费的Class实现MessageListenerOrderly接口即可。在多线程消费场景下,一个线程只去消费一个队列上的消息,那么自然就保证了消息消费的顺序性,同时也保证了多个线程之间的并发性。