作者介绍:许超,VIPKID 资深 DBA 工程师。
本文次要分享 TiDB 4.0 版本在 VIPKID 的一个利用实际。次要波及两个局部,第一局部是当初 TiDB 在 VIPKID 的一些利用场景,第二局部是介绍一下 TiDB 4.0 给咱们带来哪些惊喜和收益。
TiDB 在 VIPKID 的利用场景
首先简略介绍一下 VIPKID,VIPKID 是一家在线少儿英语教育公司,专一于服务 4-15 岁的青少儿和他们家长们,次要提供北美外教一对一授课服务,目前曾经有超过 70 万的付费用户。
场景一:大数据量及高并发写入
回归主题,TiDB 在 VIPKID 的第一个利用场景是一些大数据量和高并发写入的场景,如下图所示:
举其中一个例子,咱们当初有一套教室排障的零碎,这套零碎会实时收集教室内的一些事件信息,比方进出教室还有教室内服务初始化的信息,这些信息是通过家长端还有老师端对立上报的,业务同学能够依据这些信息疾速定位到教室内的故障,并且做一些排障伎俩,比如说切换线路之类的来保障一些上课品质。
这套零碎目前 TPS 峰值在 1 万左右,每天的新增数据量大略有 1800 万,这张表只保留最近两个月的数据,目前单表有 12 亿左右,数据量其实相对来说曾经比拟大了,这种数据量如果当初放在 MySQL 里保护老本比拟高,所以咱们把这套零碎的数据整个迁徙到 TiDB。
在迁徙过程咱们做了一些小的变动,在原有表的根底上把原来的自增 ID 去掉了,在建表的时候通过指定配置做一下事后打散,防止高写入量的时候呈现写热点问题。对于热点定位,其实 TiDB 自身之前就提供了很多形式了,比方 3.0 版本其实通 information_schema.TIDB_HOT_REGIONS
这张表就能够定位,或者间接能够在 PD 里获取相应的热点 Region 信息,然而通过这种形式拿到的其实只是一个 Region ID,还须要调用具体的 TiDB server 的 API 来获取定位到具体的表或者索引。在 4.0 里,TiDB Dashboard 让热点直观地出现在咱们背后,咱们能够间接看到热点写入量、读取量等等热点信息。
场景二:外围模块分库分表后的多维度查问
第二个场景是当初咱们的很多外围业务在晚期就曾经做了分库分表,比方约课表。对分库分表比拟理解的同学其实晓得,个别分库分表的状况下只会以一个业务列作为 Sharding Key 做拆分,然而约课表这种状况下可能波及到的维度比拟多,既有教室、老师、学生还有课程;另外可能其余端也会拜访这部分数据,比方老师端来拜访这部分数据的时候他可能会以老师的维度来拜访,如果做拆分的时候是以学生的维度拆分的,那么老师的拜访申请会播送到所有分片上,这在线上是并不容许的。针对这个问题,咱们最开始有两种解决方案,一种是咱们把所有的数据汇聚完放在 ES,还有一种形式是业务双写,写两套集群,两套集群以各自的维度拆分。无论哪种计划,不论是对 RD 来说还是对咱们 DBA 来说保护老本都比拟高。
所以咱们就借助 DM,通过 DM 将上游所有分片的表实时同步到上游,并且合并成一张全局表,所有的跨维度的查问,无论是治理端经营平台,还是业务指标监控的零碎都走 TiDB 这套零碎,查这张全局表,如下图所示:
再简略介绍一下 DM 分库分表的逻辑,其实逻辑绝对比较简单,DM 其实会拉取线上所有分片的 Binlog 日志,而后依据黑白名单过滤匹配出须要同步的那局部 binlog event,再去匹配制订的路由规定,通过改写而后利用到上游的全局表里,这里也辨别两种状况:一种状况是上游的分库分表蕴含全局 ID,这种状况其实人造的防止了合并之后的主键抵触的问题。还有一种是没有全局 ID 的状况,这种状况之前官网提供了一个解决方案是通过 Column mapping 的形式,其实就相当于对 ID 列在同步之前做一些预处理,解决之后相当于在底层同步的时候就不会有主键抵触的问题了。然而咱们和 PingCAP 同学沟通了一下,其实他们当初曾经不倡议用这种形式了。所以咱们换了另外一种形式,因为咱们的业务对于这种自增 ID、主键 ID 是没有业务依赖的,所以在上游 TiDB 这块我其实提前建了下图所示的这样一张表,而后把对应 ID 的主键属性和自增属性去掉,并且将这个 ID 退出我原先仅有的一个联结的惟一索引里就解决这个问题了:
在 DM 这块咱们简略地做了两件事。第一是 DM 的提早监控,其实 DM 自身反对提早监控,也是通过写心跳的形式去做的,但在咱们线上把 DM 并不是挂在 MySQL 集群的主节点下,而是挂在一个只读存库上,所以咱们不太容许 DM 间接去写存库的心跳。咱们线上有一套心跳机制来监控提早,所以在理论 DM 这块提早监控理论复用的是线上的那套心跳表,相当于把线上的那套心跳间接同步下来,也是通过路由规定匹配一下,而后改写。这样的话尽管在 TiDB 里可能波及到多个集群,但其实每个集群对应独自的一个心跳表,这样就能够做 DM 的提早监控。在下图里大家能够看到,大部分状况下分库分表合并的场景同步提早根本都在 200 毫秒以内:
第二件事就是解决 DM 高可用问题,因为 DM 自身并不具备高可用性,可能一个 DM worker down 的时候可能反对主动拉起,但如果呈现整个节点 down 的状况下其实是大刀阔斧的。如下图所示,咱们做了一个简略的尝试:
相当于把 DM-master、DM-worker 的所有的长久化的数据全放在共享存储上,DM-worker 是通过容器启动的,如果产生节点宕机的状况下,只须要在备用机上把对应的 worker 提起来,并且关联到本人指定的 DM-worker 的共享存储上 DM 的门路就行。这里有一个问题是 IP 是固化不了的,所以在这个过程中还须要去变更 DM-master 的配置文件,之后做一次 Rolling Update。
场景三:数据生命周期治理
TiDB 在 VIPKID 的第三个场景其实就是在数据生命周期治理。如果用过 MySQL 的都晓得,其实大表在 MySQL 里保护起来老本是比拟高的,所以个别很多公司会做逐级的数据归档。咱们当初是依据具体业务,依照读写状况将数据划分成多个等级,并把其中温数据、冷数据,其实还有线上读流量的放在 TiDB 里。
这个场景里引入 TiDB 的思考是要把数据的流转、运行起来的一个前提要保障冷热数据的表构造统一,但理论状况是,冷数据大部分状况下比热数据体量大很多,比方线上热数据做了一次表构造变更,比方加一列,同时如果冷数据同样要做这个操作,老本其实是很高的,可能是热表的十几倍或者几十倍都有可能,因而咱们想借助 TiDB 来做这个事件。自身一方面 TiDB 的 DDL 有一些个性,加字段、减字段都是秒级的,另一方面就是借助 TiDB 自身的程度扩大的能力,咱们能够每个业务端复用一套 TiDB 归档集群。上面再简略总结一下咱们在应用 TiDB DDL 的相干教训,如下图所示:
左半局部我列了几个绝对比拟常见的 DDL 操作,比方删表、删索引,其实在 TiDB 里分了两步做,第一步只变更元数据,这时候就曾经秒级返回给用户了,剩下理论数据的清理,是放在后盾通过 GC 异步来解决的。而增加索引操作因为波及到数据的填充和重组,所以这个操作的工夫是依赖于数据量,然而并不会阻塞线上业务,我之前看了一下官网的介绍,TiDB 中数据填充的过程被拆分为多个单元,每个单元外部并发进行读写操作。线上更常见的是删列和减列,在 TiDB 里跟 MySQL 的实现就不一样了,也只是变更元数据就行了,并不需要做底层的数据的 rebuild,比方减少一个列,并不需要对原始数据再做一个回填,这里分两种状况,一种是默认值是空的,一种是有一个指定的默认值,其实只须要把这个默认值记录到 TiKV 里跟表构造记录在一块,当你查问这个数据对列值做 decode 的时候,如果是空的,间接返回空;如果是有指定的默认值的,间接返回指定默认值,并不需要对历史数据做变更。
场景四:实时数据分析的场景
还有一个场景就是做实时数据分析的场景,下图其实是最早 TiDB 在 VIPKID 引入的一个场景:
这个场景次要是 BI 分析师还有一些 BI 平台在用,架构上,相当于通过 DM 把线上的数据全副同步到 TiDB 里,借助 TiDB 的程度扩大能力,还有一些计算下推的能力,做一些实时数据分析。
TiDB 4.0 给咱们带来哪些惊喜和收益?
TiFlash 列式存储引擎
TiFlash 是一个列式存储引擎,相对来说对 AP 场景更敌对一些,并且他自身本人有计算能力,反对一些算子下推、计算减速。另外,TiFlash 能够实时复制 TiKV 中的数据,并且没有突破之前 TiKV 的运行模式,它把本人作为一个 Learner 角色退出之前的 Raft Group 里能够反对表粒度的同步;还有一个就是智能抉择,TiFlash 能够主动抉择应用 TiFlash 列存或者 TiKV 行存,甚至在同一查问内混合应用以提供最佳查问速度,它曾经不仅仅是单纯的一个 SQL 抉择哪种存储引擎,粒度能够细化到同一个 SQL 里具体某个算子,比方一个 SQL 打过去,一部分能够走索引的其实走行存更快,还有一部分波及到全表扫描的走列存,通过这种形式整体进步 SQL 查问速度。最初,TiFlash 反对独立部署,能够跟 TiKV 独立离开,某种程度上做到了硬件资源的隔离。
上面谈谈 TiFlash 给咱们带来的收益。
首先是性能晋升,我这里做了一个简略测试,测试环境当初是有五个 TiKV 节点,一个 TiFlash 节点,有一个单表 2.5 亿数据,而后我对这个单表做 count,在 TiKV 里走了索引的状况下跑了 40 多秒。而在单个 TiFlash 场景下 10 秒就跑进去了,这只是单个 TiFlash 节点,如果我再新添一些 TiFlash 节点,这个速度应该还能够进一步提高。
<div class=”caption-center”>TiFlash</div>
<div class=”caption-center”>TiKV</div>
第二是老本的降落,咱们原来有一套给 BI 用的集群,当初用新的 TiDB 4.0 的集群替换了,能够看一下下图右边的表格是新的 4.0 的集群各个组件资源分配比例,右边是新、老集群同样负载状况下的资源分配状况。能够看到,部署新集群让咱们整体老本降落了 35%。
第三 TiFlash 上线解决了一些稳定性的问题。之前在 TiKV 这一层如果跑了一些 TP 业务,这时候有一个 SQL 波及到一个全表扫描,整个 TiKV 的集群负载就会变大,可能导致 TP 查问整体响应工夫变长。当初我能够退出一个 TiFlash 节点,把对应集群里的大表主动增加一个 TiFlash 的正本,在这种状况下如果有一些相似的状况,能够优先会走 TiFlash,而保障 TiKV 尽量不受影响。
再说两点咱们在应用 TiFlash 过程中遇到的一些“限度”。
第一,如果你的 SQL 中波及到一些 TiFlash 还没有实现的函数,其实是无奈做到计算下推的,只是利用到了 TiFlash 自身作为列存的一个减速能力(注:如果有尚未实现的下推需要,能够与 PingCAP 官网分割技术支持,增加微信号 XXX,备注“TiFlash 技术咨询”即可)。
第二,当初 TiFlash 对大表和大表之间的 JOIN 场景其实笼罩的还不够好,只针对小表和大表之间的 Join 做了一些优化(当然起初咱们通过 PingCAP 同学理解到他们 7 月会公布一个优化大小表 JOIN 的性能,能够让若干小表 JOIN 大表比现有计划数量级晋升的优化,并且他们往年也会开始陆续优化剩下的 JOIN 场景)。如果大家对 Spark 比拟理解的话,可能晓得 Hash Join 其实有几种算法,其中一种相当于把一张小表播送到各个数据节点,而后在数据节点本地做 Hash Join 操作,能够看到下图右边的截图,是咱们一个老师招募相干的一个大屏统计:
这个查问执行了大略 17 分钟,理论过程中也拜访了 TiFlash,但整体的工夫其实都消耗在 Hash Join 了,在 TiFlash 上耗费的时候并不多,图上能够看到 TiDB server 这一侧整体负载很高,所以瓶颈是在 TiDB server 这块。
因而咱们就思考怎么把 Hash Join 这块打散,而后咱们引入了 TiSpark。如下图所示:
通过比照测试(单个 TiDB server 是 8C 64G 的),调配同样的计算资源给一个小的 TiSpark 集群跑了一个同样的查问,耗时差不多是原来的大略三分之一。下图是革新后给 BI 用的一个 TiDB server 的集群:
这里次要增加了 TiSpark 的组件和 TiFlash 的组件,因为大屏展现 SQL 能够明确,所以很多间接走了 TiSpark,而 BI 分析师和 BI 平台的查问统计,间接走 TiDB,而后智能抉择让它走 TiKV 还是 TiFlash。
TiDB Dashboard
TiDB 4.0 中内置的 Dashboard 在我的了解里,其实是 TiDB 在产品易用性、“开箱即用”层面做了一次很大的晋升。
在 3.0 版本像热点的问题也是有形式能够查的,然而相对来说可能有肯定的学习老本,另外可信息比拟零散。当初 4.0 版本把这些都放在了 Dashboard 里,以一个更直观的形式展示给用户。而后就是 Dashboard 里比如说像日志收集还有慢日志这块,这块其实跟方才的逻辑一样其实就是为了让用户能够更简略的应用 TiDB,如果没有这些货色的话,用户集群小的话能够去具体节点下来查,如果集群规模比拟大,可能用户要本人筹备一套日志提取、日志上报的货色,其实是存在肯定的落地老本的。还有一块是在集群诊断这一块,集群诊断这块像咱们的业务其实每周有一个定期的流动,有时候研发会说我这周和上周的量并没有显著的变动,但其实感觉到下边的响应工夫变长了,其实能够生成指定的诊断报告,里边我能够明确一个基准的区间做比照:
Backup & Restore
之前 TiDB 在备份这块相对来说绝对空白了一点,只反对逻辑备份,但说大数据量的状况下逻辑备份效率是很低的,所以当初 4.0 中的 BR 工具偏物理备份,还是让人很受鼓励的。
BR 自身的程序去跟 PD 通信,来获取以后的工夫戳,还有目前 TiKV 的散布状况,并且 BR 本人在外部启动一个长期的 TiDB 实例,去构建一个备份相干的申请信息,并且将申请信息发给各个 TiKV 节点,所以这个过程中备份其实是一个分布式的备份,指定的 TiKV 节点会只备份本人以后实例上的主节点,做相似于物理备份,当他把 Region Leader 备份完了之后会把对应的元数据返回给 BR,BR 会把这些元数据保留在一个独自的文件里,而后待复原的时候应用。
咱们简略试用了一下,如下图所示:
咱们按官网的倡议,以共享存储的形式来做备份,相当于在 BR 那台机器还有所有 TiKV 的机器上都挂了雷同的共享存储做了一次备份,一个 2.4T 左右的 TiDB 实例备份了大略几个小时,这个工夫还能够进一步优化的,因为我看平均速度才 80 多兆,可能是受限于当初 SAS 盘带宽的问题,前期做一下调整会更快。大家从上图也能看到 BR 备份的各个目录的大小,整体备份大小能够看到大略有 700 多 G。
以上就是全副分享,谢谢大家。
本文整顿自许超在 TiDB DevCon 2020 上的演讲。