请问微服务架构下,有什么方式能确保消息队列在同一个服务集群只有一个个体收到事件?

之前的提问 中,有提到我想利用消息队列机制来达到各服务解耦

借由某种广播机制,在订单建立完成后,由订单服务发出「订单建立成功」的广播,告诉其他服务有订单建立。库存服务接收到广播后就会扣除库存,并再次发出「库存扣除成功」的广播,由订单服务再次接收。而其他不相干的服务就会忽略广播。

但碰到一个问题:在 K8S 的架构下可能同一个服务会出现多个实例(Pod),那我要如何确保各服务能确实收到事件,且不会重复触发?

目前我得到几种解决方案,但各有一些无法解决的问题,或实作上不知从何下手,方案分述如下:

  1. 在 AWS 中,可使用 SNS 发送事件,再由 SQS 服务接收事件,由各服务从自己的 SQS 领取事件,但我们云端选择 GCP
  2. 在 GCP 中有 Pub/Sub,但可能会有多台服务实例作为 Subscriber,无法确保不会重复触发
  3. Redis 本来就有提供 Pub/Sub 功能,但问题跟(2)一样
  4. 用某种方式将 Event 同时发送到同一台 Redis 的不同 DB,各服务监听不同的 DB,因事件被一服务实例领取后就会暂时锁住,所以可以确保不会重复触发
  5. 用某种方式将 Event 同时发送到不同 Redis,各服务从自己的 Redis 领取事件,同(4),因事件被一服务实例领取后就会暂时锁住,所以可以确保不会重复触发

请问有人碰过类似的状况,或了解微服务架构,能给我一些指导建议吗?

簡永哲 Leo Chien IT Director | 大師鏈 MasterChain E: s950329@hotmail.com
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 5
TimJuly

如果能做到操作是幂等的,那么处理多次也没有关系。

再来说说不幂等的怎么处理。笼统的来讲就是做一个全局的存储,记录哪些消息已经执行过了或正在执行。核心原理就是获取一个锁。

具体实现起来也是一个麻烦的事,细节很多,稍有不慎就会死锁,或者提前释放锁。

6年前 评论

當然鎖是一個好方法,但就如 @TimJuly 大所說,實現起來很麻煩

  1. 若是在各微服務自己實現鎖,就容易跟其他服務產生耦合
  2. 若是設計一個全域用來控制鎖的服務,又會大幅增加系統複雜度

所以我才會希望用我文中的方式,用 Laravel 本來就可以做到的方法來解決

6年前 评论
TimJuly

@leochien Laravel自带的处理方法会在任务超时(有可能已经执行成功)的时候重复执行。

6年前 评论

@TimJuly 之前沒有考慮到這個可能
請問 Tim 大對鎖的設計有什麼建議的方式嗎?

6年前 评论
TimJuly

@leochien

只是有这个可能,但是发生的几率不大,后续再对账吧。

锁感觉一句两句说不完啊,而且我自己理解的也不是很透彻。

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!