在pub/sub和消息队列中为多个使用者提供消息传递保证

vmdwslir  于 2021-06-08  发布在  Redis
关注(0)|答案(2)|浏览(507)

要求
一个系统经历了一些状态变化,系统的多个其他部分必须知道这一点(让我们称之为观察者),以便他们可以根据当前状态执行一些操作,观察者的操作是重要的,如果一些观察者不在线(由于一些故障,目前没有监听,但很快就会回来),在所有观察者都获得消息之前,不应丢弃该消息。
尝试用pub/sub模型来实现这一点,下面是我的发现(如果这种理解是错误的,请更正)-
发布者在特定主题上创建一个事件,多个订阅者可以使用同一条消息。此模型要么不提供传递保证(在redis中),要么保证一次传递(使用消息队列),即当一个使用者确认消息时,消息被丢弃(rabbitmq)。
例子
在db中创建一个新的person profile实体
现在,
后台验证服务必须知道这一点才能触发验证过程。
订阅服务必须知道这一点,才能向用户添加默认订阅。
现在这两个任务都很重要,互不相关,可以并行运行。
现在在队列模型中,如果订阅服务由于某种原因而关闭,bg验证过程会确认消息,消息将从队列中删除,或者如果它像大多数pub/sub一样是fire和forget,那么这两个服务无论如何都不能保证传递。
还有一点是,这两个任务都是不相关的,不需要一个接一个地触发。
简言之,我的需要是确保所有的消费者都得到相同的消息,他们应该能够单独地确认它们,只有在所有的消费者都确认上面的任何一种方法都不能做到这一点之后,消息才应该被逐出。
我有什么遗漏吗?我应该如何处理这个问题?

iyzzxitl

iyzzxitl1#

正如您所提到的,它不是您可以用redis pub/sub数据结构来控制的。
但是你可以用redis streams轻松地做到这一点。
streams将允许您使用 XADD 命令,然后控制哪些使用者正在处理消息,并确认消息已被处理。
您可以查看这些示例应用程序,它(在java中)提供了以下示例:
发布和使用消息
创建多个消费群体
管理异常
链接:
redis streams和java入门
redis streams in action(演示如何使用add/ack/pending/claim并使用redis streams和springdata构建防错流应用程序的项目)

mm9b1k5b

mm9b1k5b2#

rabbitmq的模型明确支持此场景,该模型将“交换”与“队列”分开:
发布者总是向“交换”发送消息,而“交换”只是一个无状态路由地址;它不需要知道消息应该在哪个队列中结束
使用者总是从“队列”中读取消息,该队列包含自己的消息副本,而不管消息来自何处
多个使用者可以订阅同一个队列,并且每条消息将被传递给一个使用者
最关键的是,一个交换可以将同一条消息路由到多个队列,每个队列将接收一个消息的副本
这里要理解的关键是,当我们谈论消费者“订阅”队列时,“pub-sub”设置的“订阅”部分实际上是从交换到队列的路由。
rabbitmq发布子系统可能如下所示:
在db中创建一个新的person profile实体
此事件作为消息发布到“事件”主题交换,路由键为“entity.profile.created”
exchange将邮件的副本路由到多个队列:
“验证服务”队列已绑定到此exchange,以接收与“entity.profile.#”匹配的所有邮件的副本
“订阅\设置\服务”队列已绑定到此exchange,以接收与“entity.profile.created”匹配的所有邮件的副本
使用脚本不知道有关此路由的任何信息,它们只知道消息将出现在与它们相关的事件的队列中:
验证服务在“验证服务”队列中获取消息的副本,处理并确认它
订阅设置服务在“subscription\u setup\u service”队列中获取消息的副本,处理并确认它
如果有多个使用脚本查看同一个队列,它们将在它们之间共享该队列上的消息,但仍然完全独立于任何其他队列。
下面是这个交互式可视化工具的屏幕截图,显示了这个场景:

相关问题