首页 > 解决方案 > ServiceStack Redis Mq:最终一致性是个问题吗?

问题描述

我正在考虑将单体应用程序转变为面向微服务的应用程序,这样做需要一个健壮的消息传递系统来进行进程间通信。这个想法是让微服务进程在 HA 服务器集群上运行,将要处理的请求添加到所有应用程序都可以访问的消息队列中。我正在考虑将 Redis 用作瞬态数据的 KV 存储,也用作使用 .Net 的 ServiceStack 框架的消息代理,但我担心 Redis 应用的最终一致性概念会使请求的处理不可靠。这就是我理解 Redis 在 Mq 方面的作用:

  1. 客户端 1 向节点 1 上的队列发布请求
  2. 节点 1 将使用 pub/sub 通知该队列上的所有侦听器请求的存在,并将请求异步推送到节点 2。
  3. 节点 1 上的侦听器将从节点拉取请求,其中只有 1 个会按原样获取它。请求删除的更新异步发送到节点 2,但需要一些时间才能到达。
  4. 初始请求由节点 2 接收(假设 RTT 有一点延迟),它将继续并通知使用 pub/sub 连接到它的侦听器。在从节点 1 接收到关于从队列中删除请求的更新之前,节点 2 上的侦听器也可以拉取请求。结果是两个监听器最终处理了同一个请求,这将对我们的系统造成严重破坏。

Redis 或 ServiceStack Redis Mq 的实现中是否有任何东西可以防止所描述的场景发生?还是我误解了关于 Redis 中的复制的其他内容?或者我应该放弃 Mq 的 Redis/SS 方法并使用 RabbitMQ 之类的东西,而不是我理解为符合 ACID 的东西?

标签: redisservicestack.redis

解决方案


同一条消息不可能在Redis MQ中处理两次,因为消息工作者将消息从Redis 列表支持的 MQ中弹出,并且所有 Redis 操作都是原子的,因此其他消息工作者将无法访问已从列表。

ServiceStack.Redis(Redis MQ 使用)仅支持用于 HA 的 Redis Sentinel,尽管 Redis 支持多个副本,但它们仅包含主数据集的只读视图,因此所有写入操作(如列表添加/删除操作)只能在单个主服务器上发生实例。

与使用 Redis MQ 而不是像 Rabbit MQ 这样的特定用途 MQ 的一个显着区别是 Redis 不支持 ACK,因此如果从 MQ 弹出消息的消息工作进程崩溃,那么它的消息就会丢失,而不是 Rabbit MQ如果未确认消息的状态连接断开,则 RabbitMQ 服务器将消息恢复回 MQ。


推荐阅读