PhxQueue 目前在微信内部广泛支持微信支付、公众平台等多个重要业务,日均入队达千亿,分钟入队峰值达一亿。
其设计出发点是高数据可靠性,且不失高可用和高吞吐,同时支持多种常见队列特性。
PhxQueue支持的特性如下:
同步刷盘,入队数据绝对不丢,自带内部实时对账
出入队严格有序
多订阅
出队限速
出队重放
所有模块均可平行扩展
存储层批量刷盘、同步,保证高吞吐
存储层支持同城多中心部署
存储层自动容灾/接入均衡
消费者自动容灾/负载均衡
PhxQueue 由下列5个模块组成。
Store 作为队列存储,引入了 PhxPaxos 库,以 Paxos 协议作副本同步。只要多数派节点正常工作及互联,即可提供线性一致性读写服务。
为了提高数据可靠性,同步刷盘作为默认开启特性,且性能不亚于异步刷盘。
在可用性方面,Store 内有多个独立的 paxos group,每个 paxos group 仅 master 提供读写服务,平时 master 动态均匀分布在 Store 内各节点,均衡接入压力,节点出灾时自动切换 master 到其它可用节点。
Producer 作为消息生产者,根据 key 决定消息存储路由。相同 key 的消息默认路由到同一个队列中,保证出队顺序与入队顺序一致。
Consumer 作为消费者,以批量拉取的方式从 Store 拉消息,支持多协程方式批量处理消息。
Consumer 以服务框架的形式提供服务,使用者以实现回调的方式,根据不同主题(Topic),不同处理类型(Handler)定义具体的消息处理逻辑。
Scheduler 的作用是,收集 Consumer 全局负载信息, 对 Consumer 做容灾和负载均衡。当使用者没有这方面的需求时,可以省略部署 Scheduler,此时各 Consumer 根据配置权重决定与队列的处理关系。
部署 Scheduler 后,Scheduler leader 与所有 Conusmer 维持心跳,在收集 Consumer 的负载信息的同时,反向调整 Consumer 与队列的处理关系。
当 Scheduler leader 宕机了后,Scheduler 依赖下述分布式锁服务选举出新 leader,不可用期间仅影响 Consumer 的容灾和负载均衡,不影响 Consumer 的正常消费。
Lock 是一个分布式锁,其接口设计非常通用化,使用者可以选择将 Lock 独立部署,提供通用分布式锁服务。
Lock 在 PhxQueue 中的作用有如下两点:
为 Scheduler 选举 leader;
防止多个 Consumer 同时处理一条队列。
Lock 同样也是可选择部署的模块:
若部署了 Scheduler,就必须部署 Lock 为 Scheduler 选举出 leader;
否则,若业务对重复消费不敏感,可选择不部署 Lock。
这里所指的重复消费场景是:若省略部署 Scheduler 的话,Consumer 需要通过读取配置得知可处理的队列集合;当队列有变更(如队列缩扩容)时,各 Consumer 机器上的配置改变有先有后,这时各 Consumer 在同一时间看到的配置状态可能不一样,导致一段时间内两个 Consumer 都认为自己该消费同一个队列,造成重复消费。Lock 的部署可以避免该场景下的重复消费。(注意,即使省略部署 Lock,该场景仅造成重复消费,而不会造成乱序消费)。