月活超 1.1 亿,用户超 4 亿,你也在用的「知乎」是如何在超大规模 TiDB 集群上玩转多云多活的?

导读

在“2024 新年围炉茶会”中,我分享了《TiDB 在知乎实践的那些事》话题,回顾了最近两年知乎 TiDB 实践的最新进展,以及对数据库未来发展方向的个人观点。

视频链接:

知乎应用 TiDB 历史非常久,至今总共部署了 400 多个 TiDB Server 节点, 600 多个 TiKV 节点,数据规模达到 PB 级别。知乎有一个最大的 TiDB 集群有 500 多 TB 的规模,单副本一天能存 30TB 数据,三副本能存将近 100TB 左右。在这种规模下,知乎核心场景中约 30% 的场景都运行在 TiDB 上。

从数据库版本来看,目前知乎的 TiDB 集群大概有 80% 处于 TiDB 4.x 版本,有百分之十几在 TiDB 5.4.3 版本,还有少量的 6.5 版本。应用 6.x 版本主要是因为一些新的 feature 吸引我们,比如说热点表、CDC 能力的提升、多云多活的能力等。

1 多云多活方案实践

第一个分享的实践是“多云多活”。

目前来看,知乎是 TiDB 社区中唯一一家在互联网场景里落地多云多活的。在 2023 年年初的时候,我们就多云多活架构和 PingCAP 内部的产研团队做过一些交流。

TiDB 的官方文档其实提供了很多种多云多活方案:

第一种是基于 TiCDC 的主备集群方案。通过 TiCDC 的能力能够解决一部分多云多活的需求,相当于使用 MySQL 的 Master and Slave 那种方式来用 TiDB 集群。它能解决一部分需求的原因取决于你对从库的定位,是将它定位为一个灾备库,还是一个只读库,还是承担业务一部分线上流量的库。

这种架构的关键点是什么呢?就在于 CDC 的同步能力。在 TiDB 4.x 时,CDC 的同步能力确实有点弱。之前我在上家公司的时候,个人与 PingCAP 做了 TiCDC 这个项目的合作,TiCDC 的一些场景、应用、需求,由我来提,由我去验证。比如早期的 TiCDC 经常容易 OOM,当拉取一个写入量很大的集群时,它对 TiKV 的负载影响在 20%左右,通过跟 CDC 团队一起迭代 + 优化,使得 CDC 对 TiKV 的影响降到 5% 之内。当 TiCDC 向下游 sync 的时候,它还有一些性能瓶颈,比如说 CDC 拉取得快, 但是 sync 到下游比较慢,那 TiCDC 整个内存消耗就比较大,最后就导致 OOM。后来 CDC 做了一些排序后的数据落地到文件中的改造,避免了一些 OOM 的问题 。通过这些优化,TiCDC 逐渐变得稳定可用。

还有另外一种解决方案是自适应集群方案。它是同一个数据中心里边的一个主备机房,可以通过自适应的方式去做 raft 级别的同步,可以有同城三中心、异地五中心等方式,将 TiDB 的同集群分布在不同 IDC 或者分布到不同云的方案。

我们最后选择的方案其实基于 Placement rule 的方案。我们有三个 IDC ,都是采用的某些云厂商的服务。其中有两个在线集群,在线集群集群是可以承担在线读写流量的,每一个集群里都有 TiDB Server 节点、 PD 节点和 TiKV 节点,还有一个灾备集群,基于副本 2-2-1 组成了五副本,通过 placement rule 的方式把副本投放到不同的 IDC,然后再结合 follow read 或者 steal read 的方式去承接在线的这部分流量。实现了任何一个在线机房宕机的时候,整个集群是可用的。最近这一段时间,包括一些大的云厂商,和一些很知名的 APP,都出现过不可用的故障情况。后面在讲到数据库发展的时候,也会讲到多云多活是未来必须要去解决和发展的方向。

2 数据库的稳定性建设

然后再讲一下我们做的数据库稳定性建设,具体而言也就是 TiDB 的稳定性建设。TiDB 稳定建设其实分了几个方面:

2.1 可观测能力

可观测能力的提升是解决发现问题和定位问题非常好的方式。可观测性都包括什么呢?一般来说是包括如 metric、trace、log 三点。

首先,我来讲一讲 metric。刚来到知乎的时候,我发现监控项非常多,集群版本也很多。你们去看过文档就知道了,一个 TiDB 集群相关的监控项,有差不多 90 多个。每个集群有这么多监控项,每个集群的负载不同,它触发的报警阈值可能也不同,公司采用同一套模版来渲染监控项目,这样的话,不同负载的集群在同一套报警触发阈值的情况下,就会发现我的手机晚上不断地收到预警信息,晚上根本就睡不着。metric 这个问题如果不解决其实真的很痛苦。

那么,我们是怎么解决这个问题的呢?

首先,我们对各种集群要设定不同的报警阈值,千人千面。不同集群的版本不一样,它的 metric 的表达式也不一样,它的阈值在不同版本也就不一样。你需要动态地去适配,搞成一个配置表,把这些监控项的配置实例化。针对某个集群的这套九十个指标的监控进行实例化;然后是报警配置,你可以做一些报警的聚合。之前的话,报警一发一堆,都是同一个报警。比如说有一个 schema error,这个报警可能同个集群里边有多个人、多个团队都在使用,那这个报警聚合之后就会发一条给到我们。怎么做报警聚合,怎么做报警预置,怎么做报警的定制化,发送不同人,这都是属于在 metric 做的一项。我们通过优化这些阈值报警,从最高时候的 1, 500 个 critical 的报警降到了几十个。这个东西一周几十个的话,再除上 7 天,每天就只有几个。再分分时间段,到晚上的报警也就稍微少一点, DBA 也能睡着觉了。

第二是 trace+log 一起。trace+log 是在 TiDB 定位问题的时候很好的一个手段。知乎是 all in K8s 的,基于 TiDB operator 去做了一套整体的管控。这套东西对于这一套架构来讲,你要存日志的话,其实你得需要制定一定的 PVC 去绑定相应的 PV。存储需要绑 PV,你的日志也要绑 PV。但是我们日志没有绑 PV,因为数据盘都是给 tikv 用,日志建议用动态云盘,因为价格问题就没有配置。所以,之前日志只会打到 Pod 的 100M 标准输出里边去做轮询。有时候有的集群日志特别大的时候,如果这个日志如果没有持久化到硬盘,它只能保留几分钟,可能是 10 分钟。那 10 分之前发生的一个问题,之后再去排查的时候,就会发现没日志来看了。

在跟业务线去开故障复盘会的时候,这个业务就会 argue,“你为什么没有那个日志?”排查不出来问题的时候,因为没有日志这一项可能会附带上故障责任。那这个这时候需要怎么做?我们做了一套 ELK 的体系,就是基于 filebeat 去收集各个日志,包括 TiDB 的 error log、 slow 日志, PD + TiKV 的各种日志。把这些日志收集到 Kafka,其实在 ELK 里,有 logstash 这个软件,通过 lua 来解析日志。但是对于 TiDB 的 slow log 来讲,你需要让某一类的 SQL 通过打水印的方式形成一条 SQL,来进行 slow log 的聚合,基于 lua 实现就比较麻烦了,我们自己写了一套聚合的逻辑来存储这些慢日志。

2.2 资源隔离

稳定性建设还有一方面是关于资源隔离。之前我们做资源隔离的方式比较粗犷。为什么粗犷呢?因为之前采用的方式就是一个大的 TiDB 集群,各个业务线都在集群里创建 database 使用。如果资源隔离做不好的话,就会出现 db1 的请求影响到 db2,进而产生很多的问题。

之前的使用方式是大家都混用同一批 TiDB Server。导致的问题是一旦有一些业务使用了大的 SQL,占资源比较大的一些 SQL,就会导致这个集群的稳定性抖动。其实计算资源是可以做隔离的,分别创建不同业务的 tidb server 集群来给不同业务使用,实现了 TiDB Server 这个计算侧的隔离。

另外 TiDB 有各种的 SQL 抑制策略。比如说像 Max execution time (最大可执行时间),就是 DML、Select SQL 一旦超过时间片杀不留,这是一个红线,是非常残暴的一个方式。第二个就是设定 SQL 的一些 quota。你可以通过各种 SQL 的 quota 的设定,让业务 SQL 使用的资源足够小。另外,你还可以搞一些自动化的杀 SQL 的程序,在触发最大可执行时间之前,杀掉你想杀的那些 SQL。类似于 pt-kill 的一些功能,就是杀什么用户的,杀什么类型的 SQL。这些就是稳定性建设里,非常细节的一些方面。

那在这种混用集群的情况下,存储测(TiKV)如何做资源隔离?第一种方式就是拆集群,之前混用的集群谁抖动影响别人的就把谁先拆出来,让它自己一个集群,尽量避免核心集群受到影响。之前用得比较粗犷,所有的 S、A、B、 C 级别的业务级别混用,那就需要从部署规划想办法。每个 S 级都单独给它搞一个集群,一个大业务线的 A 级的集群给它搞上三套。所有的 B、C 级以下的全都扔到一个老集群里边随便玩。这套方案涉及到大量 database 迁移,避免一个大集群里面有各种业务级别的数据库存在。做完业务拆分后就可以做 SLA 的承诺了。

其实各个业务线都有自己的 SLO 的指标,我们 DBA 是要求 SLA 指标,比如我们承诺 99.95% 的可用性。这个 99.95% 的可用性只赋予 S 级别业务。其他非 S 级的,我只保证 99.9% 的可用性。这样做了集群拆分后,我就敢跟业务去做承诺了,就能够保证自己的 SLA。这也是作为 DBA 这个行业里最核心的一个指标:稳定性是第一位的,哪怕其他事做得再漂亮,今年挂了 3 个 P0 的 DB,你的绩效肯定不好。

3 天穹平台

讲完多云多活和稳定性建设,再来说说知乎这两年在做的一个平台——天穹平台。天穹平台是用来干什么的?其实就是类似于 TiEM 加 TiDB dashboard,我们将它们整合了一下。这东西的好处是什么呢?我们想通过这套平台来管控整个 TiDB 的生命周期,把整个 TiDB 从创建到迁移,到日常运维,到下线的整个生命周期都放在一个平台上,通过点点鼠标的方式来进行运维管控。

我们搞了这套东西,把它的源数据一收集,然后去做迁移,去做管控,切 leader,包括查看日志、慢 SQL 报表、杀 SQL、监控、报警,所有东西非常全地整合到一个平台里。DBA 和业务都可以使用这个平台,业务使用平台可以创建集群,可以查看集群的 QPS。比如业务抖动了,看看是不是 TiDB 导致的,那就可以登到这个集群里面看看集群监控。比如我们结合 FinOps ,业务看看 TiDB 的成本怎么样。现在大家都在降本增效,那么你使用的库表有没有已经下线的大库表?有没有使用的资源超出自己预估?因为我们是按 GB 去把资源的费用分摊给业务的,在平台里边可以去调整他的资源的 quota,以及促使业务调整写入策略等等。

甚至他在这个平台里还可以做一些日常的 oncall 工单,比如说在 Jenkins 里边提一个 oncall,让 DBA 帮忙扩扩容,去做一些什么操作,所有事情都在天穹平台自助化处理,通过工单的方式层层审批,然后去执行好整个 TiDB 生命周期的管理。

这部分我会分享作为 13 年数据库从业者的一些想法。数据库的发展在我看来可以从三点来讲:

1 数据库的产品力

数据库的产品力就在于这个数据库实现了哪些功能?比如说 ACID 一致性、支持分布式事务、支持多租户、资源隔离等等,这些都属于属于产品力。

比如说之前 TiDB 一直在讲的高性能、很丝滑的 Scale,这就是它的产品力。产品力还有一点很重要是它的稳定性,最近其实 TiDB 在 feature 的迭代上更关注稳定性,在同一个 workload 的情况下,能够保证足够稳定。

所以,产品力就是你的产品实现了什么功能,产品的稳定性怎么样,产品的性能怎么样,实现了什么功能,这些都是你的产品力。这是一个产品最基础的东西,有了这个基础后,别人才能够认可你、能够去用你。除此之外,产品还需要一个开放完整的生态。

2 数据库的生态

生态其实就是数据怎么从另外一个 DATABASE 迁到 TiDB ,包括 DM 组件,包括最早的基于 mydumper、 myloader 搞的组件,以及 Lightning 等等。这些工具我都用过,我可以根据不同的业务场景把这些工具灵活运用。比如离线场景的数据迁移,我可以直接 dump 出来, 然后 load 进 TiDB。比如这个业务是一个新的集群,我可以直接 Lighting,直接用很底层的方式直接生成 KV 对,非常快速的直接往 TiDB 集群里导入,因为是新的集群,没有负载,怎么快怎么来。

上面说的是迁移,作为一个开源分布式数据库,数据既要进得来,也要出得去,不能说迁移进来之后,就被锁住了,这对于喜欢开源 DB 的互联网厂商来说是不可接受的。

那数据怎么出去呢?有两种方式:第一种是比较早的 TiDB binlog:Dumper +Drainer,Dumper 去 TiDB Server 里把数据传出来后进行聚合,再通过 Drainer 的方式往下游送。后来我们基于 TiCDC 替换了 TiDB binlog,通过 TiCDC 及时地将增量的数据变更导出去。

另外一个生态工具就是做备份的 BR。数据库备份是非常核心的工作,假如说你被删库了,但在 S3 或者在某个地方还能够把某一个时刻的数据给救回来。在 TiDB 上,即使遇到删库跑路,只要我们设定了足够的时间,有各种 Flashback 的一些能力,就能把数据及时地找回来。

还有监控工具。TiDB 基于 CNCF 的 Prometheus 和 Grafana 搞了一套监控体系,包括 TiDB dashboard,可以查看集群 region 的一些情况,如热力图、拓扑图以及一些要诊断的东西。

另外还有一些部署相关的工具,我经历过 TiDB ansible 时代,也经历过 tiup 时代,目前正在用 TiDB operator。这些东西都是历史的长流,滔滔不绝。

最后还有一些平台侧的工具,比如说前面提到的天穹平台,或者你们以后自己开发的 TiDB 运维管控平台,这些都是数据库的生态。

当然,还有一种生态叫做开发者生态,比如基于 TiKV 搞一套 JuiceFS,或者基于 TiKV 开发一套自己的 KV。这些都是数据库生态,能让数据进得来、管得住、出得去,一个数据库只有生态足够健全才能把整个数据库玩转。

3 数据库的场景

场景就是这个数据库解决了用户什么痛点。之前 TiDB 一直在讲自己的场景解决的是 MySQL 的分库分表,这其实是一个很好的场景,因为大厂或者中小厂里都有这个痛点,只要能把这个痛点解决了,然后足够稳定,再加上你的产品力和生态都足够好,就可以很好地去解决数据库落地这个问题。

后来 TiDB 又多了 HTAP 场景。在我看来,OLTP 和 OLAP 其实是不分家的,只是各占多少百分比。举个例子,我晚饭订饭下了一单,商家的交易系统不就是一个 OLTP 需求嘛?这个 OLTP 需求里边其实也有一些 OLAP 的需求。商家需要知道在下单的近半个小时之内,哪个菜卖得最好。商家有 10 个厨师,可能要通过实时的 OLAP 情况,分析出哪些菜卖得最好。比如我让这 10 个厨师做 10 种菜,把其他菜的厨师匀到这些卖得最好的菜上,这就是 OLAP 的实时决策价值。这个过程可能在一个数据库里发生,也可能通过一些准实时的 ETL 的方式发生,但是 HTAP 在这些场景里是有一定应用场景的。

除此之外,数据库还有一些多租户的场景。多租户其实是解决我们现在混用集群的最好利器,但是这个功能要在 7.x 才提供,我们现在还是 4.x 版本。

其他还有资源隔离、数据分布、更便宜的存储引擎等等。比如说数据分布策略,我可以把日常经常访问的最近最热的数据放到 Nvme SSD 上,把一些冷数据放到 HDD 或者 S3 上。或者 QPS 在不太高的情况下,直接把 S3 当成一个存储引擎去解决一些使用问题。

第一个方向是 AI x DB。我目前看得比较多的一个场景就是如何基于 NLP 的这种语言处理能力,把自然语言转化成 SQL。这能够帮助一些不会写 SQL 的产品和运营,想查看数据的时候,给他们带来一丝丝的爽意。

第二个方向就是 AIOps。比如说我数据库做了一些故障预警,想借助这些几 G、几十 G 的报警日志,去发现集群存在的问题,这些日志包括 access 日志、error、slow 日志。比如 slow 日志,我会根据 slow 日志所对应的 table,对应的索引使用的合不合理,去给一些 SQL 建议。还比如说当数据库出现故障的时候,AIOps 自动帮你去修复,让它有一个自愈能力,这都是 AI x DB 的一些方向。

第三个方向是数据库的多模态和多 workload。什么叫多模态?数据库底层都可以转成 KV 去存。我们有关系型数据库,还有图数据库,还有文档数据库,还有各种 KV 类型的数据库。未来,能不能搞一些类似于 TiRedis、TiMongo、TiHbase 等等的数据库?这些都是未来可以想象的东西,只要你把底层的存储搞好,再把上层的计算层搞好,就可以实现了。另外一个方向就是多 workload,这就是现在 TiDB 在讲的 TiDB Serverless,就是 pay as you use,你使用多少就付多少钱。

这些就是我认为未来数据库发展的一些方向,希望能够给大家带来一些启迪。

最后一起来回顾一下【一年一度北京线下新年围炉茶会】

3 个赞

这数据量杠杠的 :+1:

牛鼻,yyds

用的啥版本

牛鼻,yyds

好好学习,有前辈们在披荆斩棘

牛 666

牛鼻,yyds

牛 888888888888866666666666666666

很nice

very good

确实都是干货,里边的思路比解决方案对人的启发更大

1 个赞

80%的4.0.X,15%+的5.4.X,其他6.5.X

1 个赞

这投入一般公司达不到

谢谢分享,受教了~

点赞!!!

牛鼻,yyds

牛X :+1:

获益良多,感谢晓磊大佬的精彩分享 :+1: