导语 | 云原生场景,多语言、多种协议兼容,任意多的消息 Topic、任意多的消费者,性能的按需快速扩展成为消息队列基本的要求。本文是对腾讯TEG技术委员会专家工程师刘德志老师在腾讯云开发者社区沙龙 online 的分享整理,介绍基于 Apache Pulsar 的新一代存储计算分离设计的消息队列 TDMQ,希望与大家一同交流。
一、金融级别云原生消息队列功能需求
1. 腾讯计费背景介绍
腾讯计费是孵化于支撑腾讯内部业务千亿级营收的互联网计费平台,其核心是帮助用户与产品,安全、便捷的完成支付和收款,在交易过程中帮助产品盈收实现最大化。
如果把腾讯比喻为一个饭店,腾讯计费就相当于门口柜台的收费平台,你在饭店的消费,可以用微信支付、银行卡、苹果支付、QQ钱包、充值卡抵扣券或其他方式支付。
这里包括了 ToC 场景,比如用户往自己的 QB 账户充值,或者在游戏终端购买道具、游戏币,比如王者荣耀购买英雄或者皮肤等。也包括 ToB 场景,比如广告主、网红主播、腾讯云客户的扣款收费,都是通过腾讯计费这套平台提供的服务。
平台承载了腾讯公司每天数亿收入的大盘,为 180+ 个国家(地区)、万亿业务代码、100W+ 计算商户提供服务,托管账户总量 300 多亿,是一个全方位一站式计费平台。
腾讯计费平台有四个版本,分别是基础版、企业版、海外版、行业版,为众多广告客户提供服务,支持单笔上亿的交易。
2. 腾讯计费消息队列场景
MQ 的使用场景基本上是比较明确的,一般包含异步处理、应用解耦、流量削锋、消息通讯四个场景。围绕腾讯计费场景,MQ 在腾讯计费中的应用可以分为在线服务和离线准实时服务。
(1)在线服务
腾讯计费场景和电商购物具有类似的流程,有下单、价格计算、支付、发货等这些过程。区别在于我们的用户是在客户端一次点击,由后台把这些环节自动完成,特别是对于一些免密支付的场景的支持, 所以腾讯计费需要解决的核心问题是处理如此长链路请求,怎么保证最终钱货一致?
腾讯计费自研的分布式交易引擎可以解决交易过程中的应用层逻辑一致性问题,其中对于失败或者超时的情况下,借助 MQ 作为补偿处理。
比如 TCC 模式下的 commit 和 rolback 阶段出失败,以及 saga 模式的 do 和 undo 重试情况, 利用 MQ 的自动重试和海量堆积能力。另外还有消息通知场景,比如充值Q币成功后,会给用户发送购买成功 tips 。以及交易流水的内部推送,腾讯计费拥有最全最官方的计费流水,业务需要我们提供实时流水,MQ 是首选方案。
(2)离线准实时服务
系统交易是否高一致,该如何证明呢,这是一个很严肃的问题。必须通过第三方对账系统来验证,既期交易流水与资金流水的条目和金额是否完全一致,一般传统的是两方对账,既期交易流水和账单流水对比。
腾讯计费的对账有所不同,存在多方对账,混合支付(抵扣券加上其它支付)和打包发货(比如购买腾讯视频会员和QQ会员)。那么对账越实时就能越早发现问题,借助 MQ 消息通道能力,把计费相关流水实时进行收集,再通过流式计算框架对计费流水实时进行对账,同时还能做到实时监控,与交易引擎相辅相成,共同保证整个交易的时效性和一致性。
(3)其它场景
数据同步通道,比如 DB 多源同步、流水日志汇总等。对于千亿级规模的计费平台,消息队列需要具备哪些能力呢?
综上来看,首先需要具备金融级可靠性和容灾的能力,可以通过多副本、多地域保证数据的可靠性。
第二是强一致性,对于与钱打交道的产品,需要保证数据不能错乱。
第三是无线拓展、按需使用,具备水平拓展和无限堆积的能力。比如春节王者荣耀大促销活动,需要能够快速进行扩容,并且可以从计算和存储分别进行扩容。
第四是轻量 Serverless 化,能够支持租户,以及百万级 Topic,多协议接入来支持 Serverless。
最后是涵盖金融、电商、大数据分析场景,既要满足线上金融业务也能满足一定吞吐的离线场景。
腾讯计费平台基于开源 Pulsar 存储计算分离架构,支持按量使用、无限扩展、兼容主流消息队列、专为云而生的消息队列产品——TDMQ 可以满足上述这些要求。
二、TDMQ架构说明
1. 功能架构
TDMQ 的整体产品功能,和其他主流的消息队列基本功能并没有太大差别。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1201.jpg)
(1)具备高一致和高可靠的能力
具备丰富的消息类型来满足业务的复杂场景,比如秒杀活动场景下的定时消息、以及对消息顺序有要求的顺序消息等。同时原生租户设计,可以设置租户的请求频率、消息保留策略等,天然支持云模式。
(2)消费方面支持队列(Queue)模型和流式(Stream)模型
队列模型主要是采用无序或者共享的方式来消费消息。通过队列模型,用户可以创建多个消费者从单个管道中接收消息;队列模型通常与无状态应用程序一起结合使用,无状态应用程序不关心排序,但它们确实需要能够确认(ack)或删除单条消息,以及尽可能地扩展消费并行性的能力。
相比之下,流模型要求消息的消费严格排序或独占消息消费。对于一个管道,使用流式模型,始终只会有一个消费者使用和消费消息。消费者按照消息写入管道的确切顺序接收从管道发送的消息。
(3)具备多种协议的接入
首先自身提供多种原生 SDK,包括 Java、C++、GO、Python、nodejs 等,同时还可以支持原生的 Kafka 2.0.0 以后客户端接入,以及支持 RabbitMQ 4.0.2 客户端 AMQP 0.9.1 接入,降低用户的迁移成本。对于周边的大数据生态也有较好的对接,比如 flink、spark 等流式处理框架。
(4)提供完善的管理台
其中包含消息内容查询、消息轨迹等能力帮助用户快速定位问题,同时提供开放的管理 API 方便用户自定义管理。
TDMQ 特点,可以支持百万级 Topic,不会因为 Topic 的数量上涨,而对整体性能有大的影响。其次集群消费时,消费者个数不受 Topic 分区的限制,这一点对于业务使用会更简单,可以按照实际处理情况进行部署。
TDMQ 做到这些能力,与其存储分离的架构是密切不可分的。
2. 存储分离架构
TDMQ 是基于 Pulsar 内核,和其它的分布式消息队列不同,Pulsar 采用了计算和存储分离的 2 层架构:
Broker 提供消息的生产、发送和管理服务,本身并不存储任何状态信息和消息内容,可以认为是一个无状态的服务,相关的 Topic 元数据信息存在 ZK 里面。暴露给用户也是 Broker 地址,客户端首先连上任意其中一个 Broker 进行 Topic 路由寻址,接着会跳转 Topic 真正归属 Broker,为了保证数据的一致性,Topic只允许一个 Broker 可以操作。
对于这里的需要一个 Broker 节点来主持 Topic 的全局分配,以及负责均衡相关事情,比如单个 Broker 的机器资源比较紧张时,会触发该 Broker 的部分Topic转移到负载较低的 Broker 节点上。这个负载全局分配的节点是借助 ZK 的临时节点来产生的。
Bookie 提供存储层服务,采用逻辑分片存储模式,也就是 Ledger,一个 Topic 实际上是一个Ledgers 流。Ledger里面存储了具体的消息也就是 entry,Ledger 是有生命周期,根据 entry 条数以及打开的时长进行关闭,Ledger 一旦关闭是不可变的。
这个特性对数据的迁移以及恢复有非常大的好处,可以按照分片粒度进行搬迁,提升效率。其次相比分区的存储模式,可以更均匀利用集群资源。
因此基于存储分离的架构,可以很友好的支持系统的扩缩容。如果是计算层资源不足,可以非常方便的进行 Broker 扩容,同时对于 Broker 来说可以用相对比较廉价的机器来支撑。如果是存储层资源不足,添加 bk 节点也是非常简单的,新加的机器会在后续的 Ledger 写入使用,基本不需要额外的数据迁移动作。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1202.jpg)
三、数据高一致高可用实现方案说明
那么相比单体存储的分布式消息队列,怎么提供高并发和低延迟服务?其实影响 MQ 性能主要是一致性模型以及数据的组织模式。
1. TDMQ 的一致性模型
TDMQ 采用了 Quorum 策略来控制等待写应答,类似 Raft 中的 Log Replication。
写入 Topic 时需先指定3个关键参数:
- Ensemble Size (E):表示需要使用的存储节点数量;
- Write Quorum Size (W):将要写入的实际的存储节点数量;
- Ack Quorum Size (A):等待存储节点正确应答数量。
E 理论上越多写的效率会越高,但是可用性就越差,比如说 bookie 只有3个节点,E=3 的情况,这样会比较危险,任何一个节点出现问题,都会导致无法生产,所以真实生产环境一般需要> E的存储节点个数。
下面我们来看看具体的生产流程是怎么样的:
Broker 拥有 Topic 的控制权,也就相当于 Broker 为 Raft 算法中的 legder 角色,这也是为什么一个 Topic 只能归属到一个 Broker 上,但与 Kafka 不同的是 Broker 不进行数据存储,只是控制。
对于 Raft 协议核心就是保证各副本的数据最终能够达成一致,也就是 Raft 里面的有序状态机, 这需要我们的数据发送需要按照一定顺序性,也就是说发送 1 成功了,才能返回 2 成功。
对于 TDMQ 的消息 id 就是有序的,一般由 Ledger id 和 entry id 组成,同一个 Ledger id 里面的 entry id 是严格单调递增,因为 Ledger id 是由一个 Broker 管控,所以里面的 entry id 可以非常方便实现有序,Ledger id 的顺序是借助 zk 来保证全局顺序,所以整个 msgid 是满足有序的条件。
对于分布式系统可能会出现脑裂的情况,也就是可能会出现一个 Ledger id 有两个 Broker 同时在操作 ,这时存储层 bookie 会有 fence 机制来避免这种情况,保证只允许一个 Broker 写入成功其它的会返回失败。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1203.jpg)
(1)Broker写入
Broker 收到写入请求,会异步并发发送到 bookie 节点上,这个过程是可以支持 pipeline 写入,不会阻塞。
也就是发送消息 id 为 2 的时候可以不用等待 1 的结果,但是在返回结果时,会从请求的队列按照顺序依次进行返回。
如果 E> W 的情况时,会按照 entry id 按照算法算出最终写入的 bookie 列表,这样在消息读取时按照同样的算法也可以找到相同的 bookie 节点, 比如有 E=5,W=3,对于 Ledger 的 segment 元数据会记录 5 个 bookie 地址信息,读取时可以只在 3 个节点上去读取,其他两个可以不访问,减少不必要的请求, 这就是条带化写入过程,提升整理的写入速度。
(2)bookie写入
bookie 收到写入请求,首先放入一个队列中,由一个单独的任务负责按从队列中把数据写入磁盘中juro文件,也就是操作日志。
这个过程中有两个地方会影响整体的写入性能,第一个是单队列,因为我们最终要按顺序写入磁盘中,也就是说一个文件只能有一个 writer, 这里可能存在瓶颈,如果我们的物理机有多块磁盘,这样可以分散多个 juro 文件提升整体的并发度。
其次是尽量减少磁盘的操作次数, 通过组提交方式,按照时间窗口和消息长度两个维度来实现,在延迟和性能做一个有效的平衡。
操作日志并不一定是完全按照消息的 id 顺序写入,真正的消息数据会有另外一个任务异步刷入磁盘中,与操作日志写入在物理上进行隔离,写入磁盘之前会做去重和排序,这样就达到有序的效果。
所以从整个过程中来看,写入并不会有明显的阻塞环节,读写 IO 基本上是读写分离。在数据写入文件时,采用了 mmap 的方式,通过预加热文件的方式进一步提升写入效率。
在读取消息时,怎么能知道 bookie 哪部分数据是已经安全可见的呢?因为 bookie 节点并没有 leader 和 follow 的概念,这里是在 Broker 发送消息时,会带上上一次已经确认成功的确认 id,而最新的消息 id Broker 是实时知道的,因为是 Broker发起的写请求,这样就可以安全进行数据拉取了。
对于异常处理,分为两种情况,一种是 bookie 节点宕机,这时 bk 集群会自动进行修复工作,找出该 bookie 节点上存储的 legder 数据,然后借助其他正常 bookie 机器进行数据修复。
其次是 Broker 节点宕机,这时正在写入的 legder 状态处于 open, 当新的 Broker 接管该 leader,会去 bookie 节点把最后确认的消息di进行修复并进行关闭,采用新的 legder 来接受新的请求。
所以整个 TDMQ 的数据复制效率是非常高的,我们做了详细的性能测试,使用 24 核 CPU,60G 内存,万兆网卡,消息大小为 1K 进行测试,3 副本可以达到 36w,网卡到达瓶颈。相比 Kafka 在同等要求下的性能, 有非常高的性能提升。
2. TDMQ 跨城容灾
在容灾方面按照地域可以分为同城多活和异地多活,对于腾讯计费跨城容灾,业务逻辑层的多活不管同城还是异地 都比较简单些,基本上是无状态服务,可以非常方便进行切换。
而数据层相对要复杂很多,涉及到状态同步相关,虽然都是多活方案,但是实现上差别非常大。
腾讯计费早期的架构采用的是异地单活的架构,当时的业务也没有现在这么复杂。大部分请求都在一个城市完成,例如深圳,主数据库也是部署在深圳,所有的写请求必须在深圳的主数据完成,对于数据读取可以在异地。
这个架构的好处是数据是强一致,不会出现错乱的情况,缺点也很明显,如果主数据出现城市级灾难,就无法进行写服务了, 如果是一致性要求大于可用性的场景,这会是一个不错的方案。
对于同城多活实现相对容易些,数据有多个副本构成 ,在部署上采用跨机房或者 IDC 的部署方式,当某个机房或者IDC出现问题,可以切换到其他 IDC 上,数据层面一般采用一些一致性算法,数据可以保证强一致,但是极端灾难情况下不能避免。
随着业务的发展,异地多活成为必然选择。提供高质量的计费服务,这里主要涉及两个中心数据同步问题,业界主流采用 CDC 方式。CDC 方式的优势是业务解耦,分发场景可定制,适用面广。为了达到解耦的效果,大部分是通过消息队列来实现,不仅可以利用MQ的海量堆积能力来存放大量的变更流水,还可以利用多消费的处理能力来加快数据复制效率。
利用 MQ 作为跨城的数据同步通道,由于这个是异步操作,如果真的出现城市级故障,会出现少部分数据还未同步的情况,因为生产和消费时一个异步的过程,这时该怎么处理呢?
对于在线支付平台,在这种情况下,系统的可用性需要优先保证,应该接受新的支付请求,尽量减少损失。其次对于数据未同步完整的情况,部分数据处于中间状态,可以采用服务降级处理,比如直接报错的方式,具体实现上可以通过一个黑名单来屏蔽这些数据。
TDMQ 提供两种跨城容灾模式,如下图所示:
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1204.jpg)
(1)跨地域异步复制
常见的 MQ 想要做多中心的数据同步,需要业务实现一个数据搬迁的逻辑,虽然逻辑不会太复杂,但还是增加了业务的负担。如果可以通过一些配置就能实现多中心的数据同步那会一种非常棒的体验。
TDMQ 的 geo-repilcation 正好可以满足,内部实现了跨地域复制的能力,并且提供了一些保护措施,复制尽量不影响正常生产消费服务,最终各中心的数据会达成一致。
像腾讯计费内部的一些场景,比如数据统计分析的场景,由于交易系统产生的流水是分散在多个地域,而统计分析的集群通常集中在一个地域,所以最好是把数据最终汇集到一个地方,再集中处理。以及像阅文的跨洋需求,将上海的 MQ 数据同步到多伦多集群中,由于这种跨洋的网络环境更复杂以及非常不稳定,也比较适合 TDMQ 的跨地域异步数据复制模式。
(2)跨地域同步复制
对于跨城容灾要求在城市级别的,就需要 MQ 本身具备跨城的容灾能力,也就是副本需要存储在多地,比如三副本的情况,就需要保证2副本在深圳,1 副本在上海,或者 2 副本在上海,1 副本在深圳。
要想做到真正的城市级别容灾,需要保证一笔请求等待的 ack 需要至少包含同城和跨城的应答,这样才是正在意义上的跨城容灾级别。
从上图我们可以看到,相比 TDMQ 采用计算存储分离的架构,存储是 bookie 集群组成,Broker 在写消息时,首先会从 bookie 中选出一组 bookie 节点,选取的策略可以根据 bookie 部署的机架信息,由同城和跨城节点组成,其中机架信息可以通过配置进行指定。
这样可以保证副本是在多地存储,在等待ack策略上,可以根据机架信息保证等待异地的 ack 应答,可以实现真正意义上跨城容灾。
但是这里有个问题需要考虑,对于 DB 的数据同步场景,生产和消费一般是分布在两地,生产是必须跨城写入,这里的跨城访问时少不了,那么对于消费来说,是否可以不用跨城访问?
四、TDMQ 万级消费者
1. 问题探究
前文提到的 DB 数据的跨城同步场景中,MQ 采用跨城部署模式,消费时需要如果可以就近同城读取数据那么可以大大提升消费速率。
以及对于某些场景需要大量消费者情况下,比如配置更新,一项配置变更,需要上万个服务进行同步,又或者流水同步的场景,一份流水供上万个业务进行消费。本身 TDMQ 对一个 Topic 的消费者没有限制,但是如果太多势必会影响写入的效率。
所以如果可以支持只读 Broker 来分担消费的压力,这样就可以较好的解决这个问题。但是之前提到一个 Topic 的控制权只能归属一个 Broker,好像有点矛盾。
我们可以分析下,对于写操作一定只能由一个 Broker 管控,否则数据就可能会出现错乱等问题。而对于读取我们是可以让其它 Broker 来负责数据的读取,这也是存储分离带来的优势。
2. 实现思路
首先部署上存储集群共用这是基础,可以为 Ledger 单独创建一个只读的对象,这样就可以读取数据了。
这里涉及两个问题,第一个是怎么知道需要读取哪些数据,只读 Broker 和写 Broker 采用隔离部署,需要把 Topic 的元数据信息从写 Broker 上同步过来,这样我们就可以知道 Topic 对应的legder 集合,去 bookie 上读取数据。
另外一个问题是,我们怎么读取到最新的数据?
我们知道 Topic 由一组有序的 legder 流组成,并且只会有一个 legder 处于 open 状态,其它是关闭状态,并且是不能再改变的数据, 如果只读 boker 在读取关闭状态的 leder 也是就读取历史数据时,可以非常轻松进行读取,不需要进行额外的操作。而对于处于 open 状态下,也就是正在当前写 legder 上, 我们是通过 lastAddConfromdID 来确定是否有新消息。
但是前文提到 lastAddConfromdID 是由写 Broker 懒汉式的方式同步给 bookie 节点, 这样就存在一个问题,最新的一条,只读 Broker 是无法知道,bookie 里的安全 ConfromdID 也还没更新。
解决这个问题,我们需要实时告诉 bookie 节点最新的确认 id ,这样才能及时安全的进行消费, bkclient 可以通过配置按照一定频率将 lastAddConfromdID 实时同步给 bookie, 这样就可以解决最新消息读取不到的问题。
消息可以正常读取了,接下来要解决消费者偏移量同步的问题,如果不考虑数据删除问题,其实可以不用去关心消费者偏移量的问题,因为本身对于消费就是相互独立的。
如果删除策略是默认这种,消费完默认删除或者没有消息者也会删除,这样就存在一个问题,生产集群只负责生产,没有消费,这样在切换 Ledger 时,就会把之前的 Ledger 删除,因为发现没有消费者,因此需把只读 Broker 的消费关系和偏移量同步给写 Broker 上。
这就是整个只读 Broker 的设计思路。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1205.jpg)
五、DB 数据同步实践
1. 架构
TDSQL 的跨城容灾采用TDMQ作为增量日志的中间层,跨城部署。消息的生产由独立的进程binlogproductor 来完成,且工作在备节点。消息生产的高可用由 binlogproductor 来保证。
2. 生产可靠性
消息上报可靠性体现在以下两个方面:
- MySQL节点故障场景下 binlog 消息不丢;
- binlog 消息没有乱序。
binlogproductor 进程是 MySQL实例的伴生进程,主备节点均存在,与 mysqlagent 类似。所有的 binlogproductor 进程中,只有在冷备节点上运行的,才会真正的解析所在节点的 binlog,并 push 到消息队列。当发生下列异常时,binlogproductor 的工作节点会发生切换。
(1)备机延迟大,冷备角色发生迁移,即切换到另一个备机
此时,非冷备节点的解析进程中,工作线程会停止工作。新选举出来的冷备节点会接替老的节点,开始解析 binlog。
(2)备机 binlog 不正常,如 binlog 丢失,gtid 不连续
此时,冷备节点的 binlogproductor 会认为当前节点的日志有异常,此时该节点的日志解析会切换至主节点进行主机日志补偿。
因为在主机上进行 binlog 解析操作,有可能会对主节点造成影响,因此主机补偿这个流程,每次只会补偿主机一个 binlog 文件,结束后就会重新切换到备机来进行解析。如果备机发现 gitd 还是不连续,则会继续切换回主机进行补偿。
3. 消费可靠性
消息的消费由独立的服务 binlogconsumer 来完成,独立部署无状态,其负责从主城将增量日志拉取至备城并在备城数据节点重放。消费者容灾,高性能消费及冲突处理等,由消费者进程自身来保证。
MySQL 在记录 binlog 时,按照事务的提交顺序将行的改动写入 binlog 文件,因此按照 binlog 文件记录事件的顺序进行串行重放,源端和目标端数据库实例状态一定会达到一致。
但是串行重放因为速度慢,在遇到如批量更新等大事务时,容易产生较大的同步时延,适应不了对数据实时性较高的同步场景。
为了提高并发度,这里 consumer 按照每个行记录的表名和主键值进行 hash,根据 hash 值将消息投送到对应的同步线程中。
这样乱序的重放会导致数据不一致吗?答案是不会的,因为虽然是将顺序的消息序列打乱了,但是同一行的所有操作都是在同一个线程中是有序的,因此只要每个行的改动执行序列正确,最终数据是会一致。比较难的是在消费端,当出现冲突时,要支持幂等。
4. row格式binlog事件的幂等容错
实现幂等逻辑的动机有两个:
- 因为生产者实现的是 at-lease-once 模式进行消息生产,因此 consumer 这里必须要能否处理消息重复的问题,同时可以检测是否产生双写;
- 支持幂等逻辑后,便于数据的修复,且在数据同步的过程中不需要记录镜像点,便于运维。
这里幂等逻辑的设计原则就是,保证按照binlog事件的意图去对目标实例进行修改。如 insert 事件,其意图就是要在数据库中有一条 new 值标识的记录,如果遇到冲突则先 delete 再执行 insert。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1206.jpg)
六、结语
目前 TDMQ 这一产品正处在腾讯云的内测阶段,现在主要是用于米大师腾讯计费的场景下,覆盖整个交易的各个环节,包括离线和实时对帐的监控场景等。也有阅文集团这种跨洋数据同步场景下的应用,未来将会有更多产品也可以用到。
![](https://v2ce.com/wp-content/uploads/2023/03/picture-1207.jpg)
Q&A
Q:腾讯云的所有产品计费是使用同一套工具吗?
A:腾讯内部的计费,是统一使用 TDMQ 消息队列来完成相关所有的能力。具体一点就是在计费交易的核心能力、补偿的能力,从堆的能力以及消息的推送、流水的推送,这是在线方面的。离线方面的是,在实时对账中尽快发现流水中会不会有不一致的情况等。
Q:TDMQ 能用于同步数据库吗?
A:这个问题我理解的是说对数据进行多源的同步,之前我们也提到了把深圳的数据同步到上海的环境里面,我们就是基于 TDMQ 来做的。一个是保证它的容灾级别,使用了跨城部署的模式,同时在性能方面采用了 hash 方式提高并发度,可以用于同步数据库。
Q:TDMQ 和 Kafka 有什么区别?
A :从大的场景来讲,Kafka 在高吞吐量来讲是非常优秀的,在海量的数据处理情况下是非常具备竞争力的。对于金融场景来说 Kafka 的设计理念本身就是为了高吞吐量设计的,所以 TDMQ 更适合金融场景。
Q:如果所有的副本都故障了,如何处理?
A:如果副本都故障了,对于一致性的系统也就没意义了,因为高可用也不是说 100%,而是个概率问题。如果是一个城市都毁灭了,就无法谈了。在部署情况下,尽量去拷贝跨机房、跨省的方式来保证付款至少有一部分是成功的。不会让所有的付款都出现故障,这种情况比较罕见或者出现的概率极低,如果在真的出现也不是程序可以解决的问题。
Q:TDMQ 是如何保证数据一致性的?
A:这个刚刚在一致性模型中讲了很多,总结来说它比较类似于 Raft 协议,通过副本 W 和应答 A 的个数设置,.其次是写入的时候,因为消息 ID 是有序的,就可以当作一个状态机来使用,写入的时候也是按顺序的,以及发送消息时会带上上一次确认的消息 ID。
Q:DB 同步如何保证消费端的circle 按数据执行?
A:在 binlog 里面都会有 操作 ID,通过 binlog 就可以把数据还原出来。
Q7:TDMQ 还有什么合适的使用场景?
A:主要在线交易场景和离线分析等场景,另外我们正要上线一个轻量级流式处理的能力。它是一个轻量级的流式处理框架,比如在一些监控的场景,统计一段时间的请求量级或者是最大最小时候,如果借助 TDMQ 就可以轻松地算出来,能减少不少的负担,通常的做法利用计算的框架,这种场景也是简单的统计分析,也是比较合适的。
Q:TDMQ 支持什么语言开发?
A:首先它的核心是 Java 语言开发的,它的客户端包括很多语言的客户端,比如 C++、Go 这些。
Q:分步跨城时怎么检测是否一致性?
A:不管是分步跨城还是同城流程都是一致的,只不过等待 ack 的时候必须等待异步的跨城来支持这个,一个异地的 ack 才是有意义的,来防止出现只收到深圳的没收到上海的,这就不是严格的跨城一致性。
Q:TDMQ 支持延迟消费吗?
A:支持,延迟消费对在线业务也是非常重要的,比如失败重试的情况,需要延时来推过来。还有秒杀的活动,需要在特定的时间消费。所以这个是可以支持的。
Q:如何判断数据是哪个 Broker,TDMQ 有事务实践吗?
A:在存储分离架构中提到过,Topic 需要归属到某一个 Broker 上,这个和它本身的算法是有要求的,只有一个 Broker 能做写入操作。所以Topic 归属哪个 Broker 这个动作是由 TDMQ 里所有Broker 中一个主的Broker来完成的,后面的 Topic 分配由它来完成。TDMQ 事务的实践近期完成了开发,马上就上线。