有一个集合存储在 Redis 中,有多个相同的消费者访问这个集合,每读到一条数据都要持久化到数据库中,并从 Redis 中删除这条数据。
现在是通过 SCAN
遍历所有的 Key
,但是 SCAN
不支持并行操作,因为 Redis 服务是不记录状态的。
希望实现以下目标:
在并发比较高时,SCAN
命令的遍历速度明显跟不上新增的速度,导致数据越积越多,所以不能使用SCAN
了
有一个不成熟的想法,新建一个监听者,只运行一个实例,它只负责遍历 Redis 中的集合,然后通过负载均衡发送给消费者。
Redis的锁,是可以锁key的。
@Shendu.CC: 目的是要尽可能并行消费,必须在很短的时间内把集合中的数据消费完,所以加锁就有悖初衷。
最终采用的方案是通过将所有的 keys 存储在SET
集合中,通过SET.Pop()
消费,Pop()
支持并行操作,速度非常快,能够达到要求。
同时也就不需要最初的这种负载均衡的方案了。
还可以增加一个储存 监听实例的队列。redis 实例 和监听实例都可以横向扩展。
但是监听实例和redis不是一一对应的情况。 监听实例每监听完一个 redis 都会回到队列中,等待出队列。出队列的标准,是查看哪个redis实例 被监听者遍历过后处于空闲状态,如果查到了,立刻出队列去遍历这个redis实例。redis实例的状态也有空闲变成忙碌。
这样的话,效果就是多个redis,多个监听实例在同时的并行工作,而且可以横向扩展redis实例和 监听实例。而且队列中监听的实例一定要比redis实例多。
用消息队列去消费处理呢?比如kafka
如果Python的话,用multiprocessing.Queue呢?将消息写入Queue,多进程消费Queue。
可以考虑加个锁