消费端要保证消费的顺序性。
多个消息可能来源于一台机器,也可能来源于一个集群的多台机器,也可能来源多个集群。消费者如何去保证消息的有效性?
可以借助"双端列表"的数据结构实现消息节点的有效性。
场景:
- 消息1到达后,直接进行消费;
- 消息2到达后,在消息2的后继指针域中获取到消息1的key,去redis中进行查询:
2.1 若消息1不存在,那么证明消息1未达到,消息2存储到Redis;
2.2 若消息1存在且状态是已消费,那么消费者消费消息2,并且查询消息2的后继指针,查询消息3是否存在,若消息3存在,那么直接消费消息3。
2.3 若消息1存在且状态是正在消费,那么消息2阻塞1s(根据实际业务定阻塞时间,也可以通过CAS实现),1s后再次查询redis,若消息1还是正在消费,那么将消息2放入到延时队列。若消息1状态变为已消费,那么直接去消费消息2。 - 当消息3到达后,根据后继指针查询消息2,若发现消息2未消费,那么存储消息3。
注意:
- 使用Lua脚本保证修改Redis消息状态和获取消息的原子性。
- 消息的删除:消息消费后,删除Redis中消息实体,只保留状态。(例如消息3的状态是已消费,那么可以将消息1,2进行永久删除)。
- 工作窃取:当消费者空闲时,可以直接去Redis获取任务进行处理。