微信开源 PhxQueue:“三高“的分布式队列

导语 本文首先介绍了微信开源分布式队列 PhxQueue 的诞生背景及架构设计,然后着重在设计、性能、存储层 Fail over 过程三方面与 Kafka 进行了对比。期望了解 PhxQueue 或 Kafka 的读者均能从中获益。
开源地址:https://git.code.oa.com/wxg-td/phxqueue

PhxQueue 是微信开源的一款基于 Paxos 协议实现的高可用、高吞吐和高可靠的分布式队列,保证At-Least-Once Delivery,在微信内部广泛支持微信支付、公众平台等多个重要业务。

消息队列概述

消息队列作为成熟的异步通信模式,对比常用的同步通信模式,有如下优势:

  1. 解耦:防止引入过多的 API 给系统的稳定性带来风险;调用方使用不当会给被调用方系统造成压力,被调用方处理不当会降低调用方系统的响应能力。
  2. 削峰和流控:消息生产者不会堵塞,突发消息缓存在队列中,消费者按照实际能力读取消息。
  3. 复用:一次发布多方订阅。

PhxQueue诞生背景

旧队列

微信初期使用的分布式队列(称为旧队列)是微信后台自研的重要组件,广泛应用在各种业务场景中,为业务提供解耦、缓存、异步化等能力。

旧队列以 Quorum NRW 作为同步机制,其中 N=3、W=R=2,刷盘方式采用异步刷盘,兼顾了性能和可用性。

新需求

随着业务发展,接入业务种类日益增多,旧队列逐渐显得力不从心,主要不足如下:

  • 异步刷盘,数据可靠性堪忧

    对于支付相关业务,保证数据可靠是首要需求。
    目前大多数分布式队列方案是以同步复制+异步刷盘来保证数据可靠性的,但我们认为需要同步刷盘来进一步提高数据可靠性。

  • 乱序问题
    部分业务提出了绝对有序的需求,但 NRW 并不保证顺序性,无法满足需求。

另外旧队列还存在出队去重、负载均衡等其他方面的问题亟需改善。上述种种促使了我们考虑新的方案。

业界方案的不足

Kafka 是大数据领域常用的消息队列,最初由 LinkedIn 采用 Scala 语言开发,用作 LinkedIn 的活动流追踪和运营系统数据处理管道的基础。

其高吞吐、自动容灾、出入队有序等特性,吸引了众多公司使用,在数据采集、传输场景中发挥着重要作用,详见Powerd By Kafka。

但我们充分调研了 Kafka,认为其在注重数据可靠性的场景下,有如下不足:

Kafka 性能与同步刷盘的矛盾

Kafka 在开启配置 log.flush.interval.messages=1,打开同步刷盘特性后,吞吐会急剧下降。

该现象由如下因素导致:

  • SSD 写放大
    业务消息平均大小在数 1k 左右。
    而 SSD 一次刷盘的最小单位为一个 page size,大小为 4k。
    当 Kafka 对大小不足 4k 的消息进行刷盘时,实际写入的物理数据量是消息大小的数倍。导致硬盘写带宽资源被浪费。
  • 业务场景下 Producer batch 效果不好
    Kafka Producer batch,简单来说,就是把多个消息打包在一起发送到 Broker,广泛用于大数据场景。按道理,batch效果足够,是能抵消写放大的影响的。
    但业务场景下的消息生产不同于大数据场景下的日志生产,每个需要入队的业务请求在业务系统中有独立的上下文,batch难度大。即使在业务和Broker之间加入代理层,将Producer转移到代理层内进行batch,也因代理层的节点数众多,batch效果难以提高,导致写放大无法抵消。

Kafka replica 同步设计上的不足

Kafka replica 同步设计概要:

Kafka Broker leader 会跟踪与其保持同步的 follower 列表,该列表称为ISR(即in-sync Replica)。如果一个 follower 宕机,或者落后太多,leader 将把它从ISR中移除。

该同步方式偏重于同步效率,但是在可用性方面表现略显不足:

  • Broker fail over 过程成功率下降严重
    在3 replicas的场景下,leader 均匀分布在各 Broker 上,一个Broker出现故障,就意味着1/3的 leader、follower 离线,这时读写成功率下降:
    • 对于 leader 离线的 partition,暂时无法读写,需要等待 Controller 选举出新的 leader 后才能恢复;
    • 对于 follower 离线的 partition,也暂时无法读写,需要等待一定时长(取决于 replica.lag.time.max.ms,默认10s)后,leader 将故障 follower 从 ISR 中剔除才能恢复。

也就是说,任意一个 Broker 故障时,读写成功率会在一段时间内降为0。

  • 同步延迟取决于最慢节点
    在同步复制场景下,需要等待所有节点返回ack。

通过对比 Kafka replica 与 Paxos 的表现,我们认为在同步方式上 Paxos 是更好的选择:

对比项Kafka replicaPaxosPaxos好处
Broker fail over 过程成功率Leader或follower的离线均会造成短暂时间内无法读写只有 leader 的离线会造成短暂时间内无法读写单节点故障后的 fail over 过程中仍有过半成功率,对大多数不要求绝对有序的业务,换节点重试可避免失败
同步延迟需要等待所有节点返回 ack,延迟取决于最慢节点只需等待多数派节点返回 ack,最慢节点并不影响整体吞吐前端等待耗时更短

所以,我们基于 Paxos 重新设计了一套分布式队列,并且进行了包括同步刷盘之内的多项优化,完成了 PhxQueue。

PhxQueue 介绍

PhxQueue 目前在微信内部广泛支持微信支付、公众平台等多个重要业务,日均入队达千亿,分钟入队峰值达一亿。

其设计出发点是高数据可靠性,且不失高可用和高吞吐,同时支持多种常见队列特性。

PhxQueue支持的特性如下:

  • 同步刷盘,入队数据绝对不丢,自带内部实时对账
  • 出入队严格有序
  • 多订阅
  • 出队限速
  • 出队重放
  • 所有模块均可平行扩展
  • 存储层批量刷盘、同步,保证高吞吐
  • 存储层支持同城多中心部署
  • 存储层自动容灾/接入均衡
  • 消费者自动容灾/负载均衡

PhxQueue 设计

整体架构

在这里插入图片描述
PhxQueue 由下列5个模块组成。

Store - 队列存储

Store 作为队列存储,引入了 PhxPaxos 库,以 Paxos 协议作副本同步。只要多数派节点正常工作及互联,即可提供线性一致性读写服务。

为了提高数据可靠性,同步刷盘作为默认开启特性,且性能不亚于异步刷盘。

在可用性方面,Store 内有多个独立的 paxos group,每个 paxos group 仅 master 提供读写服务,平时 master 动态均匀分布在 Store 内各节点,均衡接入压力,节点出灾时自动切换 master 到其它可用节点。

Producer - 生产者

Producer 作为消息生产者,根据 key 决定消息存储路由。相同 key 的消息默认路由到同一个队列中,保证出队顺序与入队顺序一致。

Consumer - 消费者

Consumer 作为消费者,以批量拉取的方式从 Store 拉消息,支持多协程方式批量处理消息。

Consumer 以服务框架的形式提供服务,使用者以实现回调的方式,根据不同主题(Topic),不同处理类型(Handler)定义具体的消息处理逻辑。

Scheduler - 消费者管理器(可选择部署)

Scheduler 的作用是,收集 Consumer 全局负载信息, 对 Consumer 做容灾和负载均衡。当使用者没有这方面的需求时,可以省略部署 Scheduler,此时各 Consumer 根据配置权重决定与队列的处理关系。

部署 Scheduler 后,Scheduler leader 与所有 Conusmer 维持心跳,在收集 Consumer 的负载信息的同时,反向调整 Consumer 与队列的处理关系。

当 Scheduler leader 宕机了后,Scheduler 依赖下述分布式锁服务选举出新 leader,不可用期间仅影响 Consumer 的容灾和负载均衡,不影响 Consumer 的正常消费。

Lock - 分布式锁(可选择部署)

Lock 是一个分布式锁,其接口设计非常通用化,使用者可以选择将 Lock 独立部署,提供通用分布式锁服务。

Lock 在 PhxQueue 中的作用有如下两点:

  • 为 Scheduler 选举 leader;
  • 防止多个 Consumer 同时处理一条队列。

Lock 同样也是可选择部署的模块:

  • 若部署了 Scheduler,就必须部署 Lock 为 Scheduler 选举出 leader;
  • 否则,若业务对重复消费不敏感,可选择不部署 Lock。

这里所指的重复消费场景是:若省略部署 Scheduler 的话,Consumer 需要通过读取配置得知可处理的队列集合;当队列有变更(如队列缩扩容)时,各 Consumer 机器上的配置改变有先有后,这时各 Consumer 在同一时间看到的配置状态可能不一样,导致一段时间内两个 Consumer 都认为自己该消费同一个队列,造成重复消费。Lock 的部署可以避免该场景下的重复消费。(注意,即使省略部署 Lock,该场景仅造成重复消费,而不会造成乱序消费)

Store 复制流程

在这里插入图片描述
PhxQueue Store 通过 PhxPaxos库 进行副本复制。

PhxPaxos 的工程实现方式分为三层:app 层负责处理业务请求,paxos 层执行 paxos同步过程,状态机层更新业务状态。

其中,app 层发起 paxos 提议,paxos 层各节点通过 paxos 协议共同完成一个 paxos log 的确认,之后状态机以 paxos log 作为的输入作状态转移,更新业务的状态,最后返回状态转移结果给 app 层。

一致的状态机层,加上来自 paxos 层的一致输入,就产生一致的状态转移,从而保证多个节点强一致。

这里我们要基于 PhxPaxos 在状态机层实现一个队列,就需要作如下概念映射:

队列概念PhxPaxos概念PhxPaxos概念解析
队列数据paxos logpaxos 日志,其值由 paxos 算法确定,在各节点内强一致
队列偏移instance idpaxos 日志的唯一编号,严格递增
队列读偏移check point构成状态机镜像的最大 instance id,该 id 之前的 paxos 日志可删除
  • 队列这种模型不涉及数据修改,是有序的数据集合,和 paxos log 的定义很像,所以可以让入队的数据直接作为 paxos log,而状态机只需要保存 paxos log 序列。
  • instance id 的严格递增特性,使得它可以方便地作为队列偏移。
  • 队列中读偏移之前的数据,认为是可以删除的数据,这点和 check point 的定义一致。

整体上队列状态机和 paxos 能很好地切合。

Store Group Commit - 高效刷盘及副本同步

未经优化的 Paxos 协议并未解决同步刷盘的写放大问题。而且,其副本同步效率不如 Kafka。

原因是,Kafka 的副本同步是流式批量的,而 Paxos 协议是以 paxos log 为单位串行同步,每个 paxos log 的同步开销是 1个RTT + 1次刷盘。

在多DC部署的场景下,ping 时延可达4ms,这样会导致单个 paxos group 的理论最高 TPS 仅250。

我们采用多 paxos group 部署 以及 Group Commit 的方式来同时解决同步刷盘的写放大问题以及Paxos吞吐问题。

在这里插入图片描述
如上图, 我们部署多个 paxos group,以 paxos group 作为 Group Commit 的单位,一个 paxos group 内对应多个 queue,将多个 queue 在一段时间内入队的数据合并在一起,当等待耗时或积累数据数目达到阀值,才会触发一次 Paxos 同步和同步刷盘,等待期间前端阻塞。

与 Kafka 的 Producer 批量逻辑相比,在存储层以 Group Commit 进行批量合并的好处如下:

  1. 业务层无需关注如何组织请求进行批量;
  2. 在存储层以 paxos group 为单位的聚合效果比上层聚合效果更好。

PhxQueue 与 Kafka 对比

下面分别从设计、性能、存储层 failover 过程三方面对比 PhxQueue 与 Kafka。

设计对比

PhxQueue 架构虽然与 Kafka 等常见分布式队列类似,但设计上仍有不少独特之处。为了能让对 Kafka 有一定了解的读者更方便地了解 PhxQueue,下面列出了两者的对比。

注:以下对比基于相同的数据可靠性场景:少数派节点失效,不会造成数据丢失,且整体依旧可用。

特性PhxQueue 设计Kafka 设计总结
水平扩展最小粒度queuepartition两者均以分区作为水平扩展的最小粒度,PhxQueue 定义为 queue,Kafka 定义为 partition。
物理文件存储粒度paxos grouppartition存储所用的物理文件数,决定了磁盘写并发。一个 paxos group/partition 对应着一个物理文件。与 Kafka 不同的是,PhxQueue 有意区分 queue 和 paxos group 的概念。一个 queue 只属于一个 paxos group,一个 paxos group 内可包含多个 queue,从而避免逻辑水平扩展影响写盘并发。
存储层的可写角色masterleaderPhxQueue 与 Kafka 均只有 master/leader 可写。
存储层 master(leader) 分布自动均匀分布到各节点自动均匀分布到各节点PhxQueue 与 Kafka 均支持 master(leader) 自动均衡,分摊接入压力到各节点。
存储层 master(leader) 选举Store 自身依赖 Paxos 选举 masterBroker 依赖 Zookeeper 选举出 Controller,再由 Controller 选举出各分区的 leaderKafka Broker 引入 Controller 解决了 Zookeeper 压力大的问题;PhxQueue Store 不依赖外部选举,每一组均能独立进行 Paxos 决议,分散了选举压力。
批量生产能力Producer、Store 均有独立的 batch 逻辑仅 Producer 有 batch 逻辑batch 逻辑是提高吞吐的杀手锏。PhxQueue 为了应对高扇入场景下 Producer 端 batch 效果不好的情况,在 Store 中加入了 batch 逻辑。
生产确认Paxos 协议,多数派 accept 即完成同步全同步协议,所有 ISR 返回 ack 后完成同步PhxQueue 只需多数派应答即可完成同步,Kafka 同步需要等待最慢节点。
存储层的组间容灾隔离对于 PhxQueue,Paxos 只要求组内多数节点存活即可完成写入,所以单节点离线造成的失败,可以在组内换节点重试成功;对于 Kafka,单节点离线会造成整组暂时不可写,重试逻辑需要换组进行,相当于一个组的请求转移到了别的组,有可能压垮别的组,牺牲了组间容灾隔离。
存储层的服务发现通过本地配置文件获取存储层信息通过 Metadata RPC 获取存储层信息PhxQueue 通过配置文件做服务发现,使用者需维护各机器配置的一致性;Kafka 以 Zookeeper 作为配置管理中心,为了避免性能下降及提高稳定性,没有直接将 Zookeeper 暴露给使用方,而是使用 RPC 的方式返回信息。
消费隔离以订阅(Sub)为单位以消费分组(Consumer Group)为单位两者均支持消费隔离。
消费管理各 Consumer 与 Schduler 维持心跳并上报负载,Schduler 根据负载调整各 Consumer 的消费权重,Consumer 再根据消费权重决定要处理的队列由 Coordinator 对每个 Consumer Group 选举出一个 Consumer 作为 leader,决定该 Consumer Group 内的队列分配为了适应混合部署的场景,PhxQueue 新增了负载均衡功能,当某 Consumer 负载过高时,可自动调整分配;Kafka并无该功能。

性能对比

测试环境

CPU: 64 x Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz
Memory: 64 GB
Network: 10 Gigabit Ethernet
Disk: SSD Raid 10
Cluster Nodes: 3
Ping: 1ms

测试基准及配置

基准描述基准要求PhxQueueKafka备注
刷盘并发100并发100 queues, 100 paxos group100 partitions测试环境硬盘为 SSD,高并发能获得高吞吐
副本同步方式3 replicas3 Storesreplication.factor=3;min.insync.replicas=2;request.required.acks=-13 replicas 部署;要求一个 replica 不可用时,整体仍可用,且数据不丢
入队数据大小10字节10字节

测试结果

开启 Producer Batch:

入队 QPS(w/s)平均耗时(ms)
PhxQueue(同步刷盘)1890
Kafka(异步刷盘)18120
Kafka(同步刷盘)9290

以上场景,PhxQueue 瓶颈在 cpu,使用率达70% ~ 80%。

小结

  1. PhxQueue 性能与 Kafka 持平;
  2. 相同 QPS 下,由于不用等最慢节点返回,PhxQueue 平均耗时比 Kafka 稍优;
  3. 关闭 Producer Batch 后,在同步刷盘场景下,PhxQueue 性能可达 Kafka 的2倍,原因是,PhxQueue 存储层在写盘前做了 batch,而 Kafka 没有,所以后者会有写放大。

存储层 failover 过程对比

主要对比杀死存储层的一个节点后,对整体吞吐的影响。

Kafka

表现:

  • Failover 期间,在不同阶段程度不同,入队成功率在0% ~ 33%;
  • Failover 持续时间由租约决定,租约时长默认10s。

测试过程:

将 replica.lag.time.max.ms 从 10s 调整为 60s(延长时间方便观察),然后 kill Broker 0,挑选3个 partition,观察 ISR 变化如下:

第一阶段(未 kill Broker 0):
        Topic: test-dis-p100    Partition: 96   Leader: 0       Replicas: 0,1,2 Isr: 1,0,2
        Topic: test-dis-p100    Partition: 97   Leader: 1       Replicas: 1,2,0 Isr: 1,0,2
        Topic: test-dis-p100    Partition: 98   Leader: 2       Replicas: 2,0,1 Isr: 1,0,2
第二阶段(kill Broker 0 后持续8s):
        Topic: test-dis-p100    Partition: 96   Leader: 0       Replicas: 0,1,2 Isr: 1,0,2
        Topic: test-dis-p100    Partition: 97   Leader: 1       Replicas: 1,2,0 Isr: 1,0,2
        Topic: test-dis-p100    Partition: 98   Leader: 2       Replicas: 2,0,1 Isr: 1,0,2
第三阶段(持续1分钟左右):

 - List item

        Topic: test-dis-p100    Partition: 96   Leader: 1       Replicas: 0,1,2 Isr: 2,1
        Topic: test-dis-p100    Partition: 97   Leader: 1       Replicas: 1,2,0 Isr: 2,1,0
        Topic: test-dis-p100    Partition: 98   Leader: 2       Replicas: 2,0,1 Isr: 2,1,0
第四阶段(至此入队成功率完全恢复):
        Topic: test-dis-p100    Partition: 96   Leader: 1       Replicas: 0,1,2 Isr: 2,1
        Topic: test-dis-p100    Partition: 97   Leader: 1       Replicas: 1,2,0 Isr: 2,1
        Topic: test-dis-p100    Partition: 98   Leader: 2       Replicas: 2,0,1 Isr: 2,1

其中,第二/三阶段入队成功率受损:

  • 第二阶段期间,Partition 96/97/98 均无法写入,入队成功率成功率下降至0%。
  • 第三阶段期间,Partition 96 可继续写入,但 Partition 97/98 无法写入,因为写入要等 Broker 0 回 ack,但 Broker 0 已 kill,入队成功率下降至33%。

而实际观察,第二/三阶段期间完全没吞吐,原因是压测工具不断报连接失败,停止了写入。

压测工具输出:

30551 records sent, 6107.8 records/sec (0.06 MB/sec), 1733.9 ms avg latency, 5042.0 max latency.
30620 records sent, 6117.9 records/sec (0.06 MB/sec), 1771.9 ms avg latency, 5076.0 max latency.
30723 records sent, 6123.8 records/sec (0.06 MB/sec), 1745.4 ms avg latency, 5009.0 max latency.
30716 records sent, 6127.3 records/sec (0.06 MB/sec), 1841.1 ms avg latency, 5299.0 max latency.
30674 records sent, 6133.6 records/sec (0.06 MB/sec), 1621.3 ms avg latency, 4644.0 max latency.
>>>>>>>>>> kill Broker 0 here (入队成功率受损)>>>>>>>>>>
10580 records sent, 123.4 records/sec (0.00 MB/sec), 1537.1 ms avg latency, 84236.0 max latency.  <<-----吞吐下降严重
11362 records sent, 132.3 records/sec (0.00 MB/sec), 1658.3 ms avg latency, 84232.0 max latency.
11367 records sent, 132.3 records/sec (0.00 MB/sec), 1582.4 ms avg latency, 84228.0 max latency.
11236 records sent, 130.9 records/sec (0.00 MB/sec), 1694.2 ms avg latency, 84240.0 max latency.
11406 records sent, 132.8 records/sec (0.00 MB/sec), 1650.5 ms avg latency, 84233.0 max latency.

压测工具连接Broker失败日志:

[2017-08-16 15:38:22,844] WARN Connection to node 0 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
[2017-08-16 15:38:22,859] WARN Connection to node 0 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
[2017-08-16 15:38:22,865] WARN Connection to node 0 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
[2017-08-16 15:38:22,868] WARN Connection to node 0 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)

原因分析:
Kafka Broker leader 是通过 Controller 选举出来的,ISR 列表是 leader 维护的。

前者的的租约是 Controller 定义的,后者的租约是 Broker 配置 replica.lag.time.max.ms 指定的。

所以,第二阶段持续时间较短,是 Controller 的租约时间决定的,第三阶段持续时间较长,是 replica.lag.time.max.ms 决定的。

当 Broker 0 被 kill 时,前者影响本来 Broker 0 是 leader 的 1/3 partitions 的入队成功率,后者影响 Broker 0 作为 follower 的 2/3 partitions 的入队成功率。

PhxQueue

表现:

  • Failover 期间,入队成功率仅下降至66%;
  • Failover 持续时间由租约决定,租约时长默认5s。
  • 开启 换队列重试特性(适合没有绝对顺序性要求的业务提高可用性)后,Failover 期间仍有90+%入队成功率。

测试过程:

将 Store master 租约时长从10s调整为60s(延长时间方便观察),然后kill store 0,观察某 Producer 入队成功率:

关闭换队列重试特性:

>>>>>>>>>> kill store 0 here (入队成功率受损)>>>>>>>>>>

-------------------------------------------
--      total:  192323
--      time(ms):       10015
--      qps:    19203.49
--      routine_sleep:  73.88%
--      retcode cnt     percent
--      -1      22097   11.49 <<---------------------- 失败:连接失败
--      0       125905  65.47 <<---------------------- 成功:仍有66%成功率
--      10102   44321   23.05 <<---------------------- 失败:提示需要重定向到 master
--      usetime(ms)     cnt     percent
--      < 1             0       0.00
--      < 2             0       0.00
--      < 5             610     0.32
--      < 10            7344    3.82
--      < 20            18937   9.85
--      < 50            36067   18.75
--      < 100           6971    3.62
--      < 200           20239   10.52
--      < 500           59059   30.71
--      < 1000          30601   15.91
--      >= 1000         12495   6.50

>>>>>>>>>> (入队成功率完全恢复)>>>>>>>>>>

-------------------------------------------
--      total:  198955
--      time(ms):       10001
--      qps:    19893.51
--      routine_sleep:  98.00%
--      retcode cnt     percent
--      0       198955  100.00 <<---------------------- 成功:100%成功率
--      usetime(ms)     cnt     percent
--      < 1             0       0.00
--      < 2             2       0.00
--      < 5             5895    2.96
--      < 10            30830   15.50
--      < 20            65887   33.12
--      < 50            95403   47.95
--      < 100           753     0.38
--      < 200           185     0.09
--      < 500           0       0.00
--      < 1000          0       0.00
--      >= 1000         0       0.00

开启换队列重试特性:

>>>>>>>>>> kill store 0 here (入队成功率受损)>>>>>>>>>>

-------------------------------------------
--      total:  134752
--      time(ms):       10001
--      qps:    13473.85
--      routine_sleep:  77.43%
--      retcode cnt     percent
--      -202    14      0.01 <<---------------------- 失败:超时
--      -1      2712    2.01 <<---------------------- 失败:连接失败
--      0       127427  94.56 <<------------------------- 成功:仍有94%成功率
--      10102   4572    3.39 <<---------------------- 失败:提示需要重定向到 master
--      10105   27      0.02 <<---------------------- 失败:master 未选举出来
--      usetime(ms)     cnt     percent
--      < 1             0       0.00
--      < 2             4       0.00
--      < 5             3284    2.44
--      < 10            10704   7.94
--      < 20            22109   16.41
--      < 50            32752   24.31
--      < 100           4541    3.37
--      < 200           4331    3.21
--      < 500           11265   8.36
--      < 1000          19706   14.62
--      >= 1000         26056   19.34

>>>>>>>>>> (入队成功率完全恢复)>>>>>>>>>>

-------------------------------------------
--      total:  198234
--      time(ms):       10014
--      qps:    19795.69
--      routine_sleep:  94.36%
--      retcode cnt     percent
--      0       198234  100.00 <<---------------------- 成功:100%成功率
--      usetime(ms)     cnt     percent
--      < 1             0       0.00
--      < 2             0       0.00
--      < 5             3875    1.95
--      < 10            22978   11.59
--      < 20            53000   26.74
--      < 50            87575   44.18
--      < 100           6204    3.13
--      < 200           6468    3.26
--      < 500           11963   6.03
--      < 1000          5637    2.84
--      >= 1000         534     0.27
小结
  1. 在存储层 failover 过程中,PhxQueue 和 Kafka 的入队成功率均有一定时长的下降,PhxQueue 的入队成功率在66% ~ 100%,Kafka 的入队成功率在0% ~ 33%;
  2. PhxQueue 开启换队列重试特性后,failover 过程中入队成功率保持在90+%。
  3. PhxQueue 和 Kafka 均能自动切换 master,最终入队成功率完全恢复。

总结

PhxQueue 在存储层做了很多的努力:实现了 master 自动切换,且仍然保证线性一致,切换期间仍然高可用;保证了同步刷盘的吞吐,其性能不亚于异步刷盘。

另外实现了大部分队列实用特性,例如出入队顺序一致、多订阅、限速、消息重放等,适用于各种业务场景。

目前 PhxQueue 已在微信内部大规模使用,也正式开源。

我们将保持 PhxQueue 开源版本与内部版本的一致,欢迎读者试用并反馈意见。

开源地址:https://github.com/Tencent/phxqueue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值