我一直在寻找使用Redis Pub/Sub作为RabbitMQ的替代品.
根据我的理解,Redis的pub/sub与每个订阅者保持持久连接,如果连接终止,所有将来的消息都将丢失并丢弃在地板上.
一种可能的解决方案是使用列表(和阻塞等待)将所有消息和pub/sub存储为通知机制.我认为这让我大部分都在那里,但我仍然对失败案件有一些担忧.
小智 35
当订户(消费者)死亡时,您的列表将继续增长,直到客户返回.一旦达到特定限制,您的生产者可以修剪列表(从任何一方),但这是您需要在应用程序级别处理的内容.如果在每条消息中包含时间戳,则您的消费者可以根据消息的年龄采取行动,假设您具有要在消息期限上强制执行的应用程序逻辑.
我不确定格式错误的消息将如何进入系统,因为与Redis的连接通常是TCP及其完整性保证.但是如果发生这种情况,可能是由于生产者层的消息编码中的错误,您可以通过保持接收消费者异常消息的每个生产者队列来提供处理错误的一般机制.
重试策略在很大程度上取决于您的应用程序需求.如果您需要100%确保已收到并处理了邮件,那么您应该考虑使用Redis事务(MULTI/EXEC)来包装使用者完成的工作,这样您就可以确保客户端不会删除邮件,除非它已经完成了它的工作.如果需要显式确认,则可以在专用于生产者进程的队列上使用显式ACK消息.
如果不了解您的应用需求,很难知道如何明智地选择.通常,如果您的消息需要完整的ACID保护,那么您可能还需要使用redis事务.如果您的消息仅在及时发布时才有意义,则可能不需要进行交易.听起来好像你不能容忍丢弃的消息,所以你使用列表的方法是好的.如果需要为邮件实现优先级队列,则可以使用排序集(Z命令)来存储邮件,使用其优先级作为分数值,以及轮询使用者.
如果您想要一个订阅者在死亡时不会丢失消息的 pub/sub 系统,请考虑使用Redis Streams而不是 Redis Pub/sub。
Redis Streams 有自己的架构以及 Redis Pub/sub 的优缺点。使用 Redis Streams,订阅者可以发出以下命令:
我收到的最后一条消息是 X,现在给我下一条消息;如果没有新消息,则等待新消息到达。
上面链接的 Antirez 文章很好地介绍了 Redis 流,并提供了更多信息。