写点什么

tidb 之旅——tidb 架构选择

  • 2023-07-07
    北京
  • 本文字数:3568 字

    阅读完需:约 12 分钟

作者: 有猫万事足原文来源:https://tidb.net/blog/f6bc5537

前言

从 4 月份开始利用 tidb 改造了我们公司 bi 系统。这个过程中,我感觉到了 tidb 的强大。也打算记录一下整个改造过程。我打算从 4 个方面来记录这个改造过程。tidb 架构选择,dm 工具的使用——这两个部分还是 tidb6.5.1,dm6.6 版本上完成的,然后是 7.1 的新特性生成列和资源管控。


这是这个系列的第一篇——tidb 架构选择篇

现状

公司经营游戏业务,有十几套 mysql 数据库,每一套对应一个游戏服,每个游戏服 mysql 结构是一样的。关键是年代久远,里面的表结构也大致在没有 dba 的情况下运行了 4-5 年。时间一长,问题就多,而且因为怕影响线上的业务和游戏体验,平时也基本不会停机维护。


最突出的问题就是数据写入没有问题,但查询非常慢,大表改造不停机又不可能,停机时间长了,老板也不接受。正好在 2022 年疫情封城的时候,我利用在家办公的时间了解过 tidb。就建议老板,可以建立一个 tidb 集群,通过 mysql binlog 把写入流量整个接过来,相当于给现有的十几套 mysql 做个读写分离。凭我对 tidb 粗浅的认知,我认为只要数据进了 tidb,就算处理的再慢,也不会影响线上的业务。而且通过 binlog 也能做到准实时的分析。老板对这个方案还是比较心动的,所以给了我一点预算,来做这个尝试。

我的目标

对我来说,平时做个报表,算个指标,改个数据,我都可以认为是正常需求。


最让人烦心的问题,在于某年某月的某一天,当业务人员找到你,指着一个指标说,这个数字是不是算错了。这个问题就是最让人崩溃的,当他问出这个问题。你就要从指标算法找起,确认算法没错,在找到详细记录,一条一条的对过去。如果是算法的问题,多少和你还有点关系。不过大部分情况是业务人员就是难以相信某个指标就是这么好 / 这么差。然后你就要陪着他这么折腾一轮。


如果有一个计算指标足够快的库,这一切就会完全不同。我可以只存储详细记录,对应的指标和维度直接做成 sql。当业务人员要看的时候算出来给他。当他觉得这个指标计算的有问题的时候,可以自己去掉维度和对应的聚合算法,直接找到详细记录。这样他有任何疑问都不用来找我了。我当然不指望新系统 100% 解决这类问题,但只要能解决 90% 也是极大的减少了我处理此类问题的精力。


实现这个目标的核心就是需要一个足够快的库,我希望 tidb 能做到这点,同时我选用了 metabase 做为 bi 的展示。metabase 处理报表的方式非常接近写一个 sql。是一个比较好的学习 sql 的拐棍。我也希望业务人员能通过 metabase 对 sql 有个感性认知,以至于最后大部分他们想查什么都可以尝试自己去点点鼠标尝试实现一下。我只要维护好基础数据就可以了。


现在回头来看,上述目标大部分应该是实现了。

tidb 的架构选择

公司资源有限,小本经营。所以一开始我也就在腾讯云上申请了 3 台 4 核 8g 的云主机,总价每月也就 1000 出头一些,这个配置在文档内只配在测试环境做 pd。


部署方式是典型的新手起步,每台 1pd1tidb1tikv。tiflash 监控这个时候还凑不出机器来装。监控更是和其他业务的测试环境挤一台。结果就是在导入 3-4g 大小的表的时候,集群就挂了。


翻了下监控,发现获取 tso 的时间巨长,应该是导入的时候,3 台 tikv 把每个机器的 cpu 都跑满了,pd 根本没有办法响应造成的。资源有限是一个现实的问题,如果我使用 8 核 16g 以上配置,成本上升的有点快。


所以我得到了第一个教训,小本经营的情况下,pd 和 tikv 不能放一起。


好在加钱也不是完全没有空间。不过提高机器配置是没可能了,现有预算增加一下机器数量还是问题不大的。


仔细考虑了一下架构,要做到任何一台挂了,整个集群都可用。那 tidb 和 pd 起码 2 个,且不能和 tikv 放一起。tikv 最好独占一台。接入写入流量主要考验整个集群的写入能力,满足最低 3 副本的基础上,我又多准备了一台 tikv。这样就要再申请 3 台同配置的机器。1pd1tidb 放两台,4 个 tikv。因为有 2 台 tidb 还需要一个粗浅的负载均衡,好在用 haproxy 不怎么占资源继续和监控放在一起——和其他业务的测试环境低负载机器挤一台。2 个 pd 经人提醒有脑裂的风险,还需要一个 pd 节点,反正 3 个 pd 只有一个会用,这个新加入的 pd 只要解决脑裂的投票问题就行,所以继续和监控 /haproxy 挤一台。


此时的成本来到了每个月 2000 出头一些。


大体的架构经过导入大表时候的表现看是稳定了。偶尔会挂的 tikv 并不影响集群的稳定。

写入热点

如果说 tidb 和 mysql 有什么显著的区别,我认为写入热点应该是排在第一的。


在我这个机器配置下,除非 mysql 的表上的数据小于 100w,照搬 mysql 的建表语句还算可以接受。


大于这个量,如果不做表结构的修改,直接导入肯定能在流量可视化里面看到写入字节量这个图里面有一条明亮的斜线。这就是写入热点。


https://docs.pingcap.com/zh/tidb/stable/troubleshoot-hot-spot-issues#tidb-%E7%83%AD%E7%82%B9%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86


对于写入热点问题,文档里面给出方案也无外乎两种:


1,聚簇索引表 +anto_random2,非聚簇索引表 +SHARD_ROW_ID_BITS+PRE_SPLIT_REGIONS


简单来说,非聚簇索引表不管你的主键如何设置都会生成一个 _tidb_rowid 来做这个表的主键。


所以查询和写入都多一次回表。而聚簇索引表就没有这一次回表。


从原理上来说,在某些场景下(在 dm 篇细说),确实聚簇索引表是更好的选择,但是记得我开头写的目标吗?我的目标是当指标计算有问题的时候,业务人员自己能找到详细记录,如果这个详细记录使用了 anto_random 和原本在游戏服数据库上的记录对不上。那我不是给自己挖坑么。在这个问题上,我宁可为难一下 tidb 也不要为难我自己。


所以对表结构的改造,我全部采用了非聚簇索引表 +SHARD_ROW_ID_BITS+PRE_SPLIT_REGIONS 的方案。上游继续用它的 anto_increment。


只要有点数据规模的(10w-100w 条)就是 SHARD_ROW_ID_BITS=2 PRE_SPLIT_REGIONS=2,预分裂 region 数 4,最高 8。


超过 1000w 的直接 SHARD_ROW_ID_BITS=5 PRE_SPLIT_REGIONS=5,预分裂 region 数 32,最高 32.


经过我的实际测试,在有 4tikv 的情况下,如果你想要负载均衡,你预分裂的数量要比 4 大一些,才容易均衡。


在对于某个大于 1000w 的表设置为 SHARD_ROW_ID_BITS=2 PRE_SPLIT_REGIONS=2 的进行大表导入测试的时候,预分裂 region4,tikv 实例也是 4,我以为会是均衡的。实际导入大表观察 4 个 tikv,其中某一个 tikv cpu 一直只有 10-20% 的负载,其他 3 台 tikv 都在 380% 左右,cpu 基本跑满。


所以之后对这种表都宁可预分裂的大一些。防止写入负载不平衡。


另外假如你做好了表结构不是立刻进行导入,还需要调整表属性。https://docs.pingcap.com/zh/tidb/stable/table-attributes#%E6%96%B0%E5%BB%BA%E8%A1%A8%E6%88%96%E5%88%86%E5%8C%BA%E7%9A%84%E5%86%99%E5%85%A5%E7%83%AD%E7%82%B9%E9%97%AE%E9%A2%98


防止预分裂的 region 被提前合并掉。当然大批量的导入完成了就可以考虑去掉了。


这就够了吗?显然不够,写入热点是一个需要时时刻刻考虑的问题。


create table t_new as select * from t;
复制代码


你要考虑 t 有多少数据,表结构是什么样的,这样复制 / 备份是否会有写入热点。


insert into t1 select * from t;
复制代码


你还是要考虑 t 有多少数据,t1 的表结构是否改造过,会不会有写入热点。


总之,写入热点问题,是一个你需要时刻注意的问题。

修改事务隔离级别

https://docs.pingcap.com/zh/tidb/stable/system-variables#transaction_isolation


tidb 的默认事务隔离级别是 REPEATABLE-READ. 这个事物隔离级别是比 READ-COMMITTED 要高的。显而易见的问题是,代价肯定也比 READ-COMMITTED 要大。关键还不讨好,大部分研发人员还是习惯 READ-COMMITTED。所以显得没有必要,改回 READ-COMMITTED,皆大欢喜。

监控告警

这是 tidb 篇的最后一个问题。当你安装好监控后,并不会收到任何信息。打开 alertmanager.yml 你会看到里面有如下配置:


route:# A default receiver  receiver: "blackhole"receivers:# This doesn't alert anything, please configure your own receiver  name: "blackhole"
复制代码


消息都发进了黑洞,你当然收不到任何东西。不开大就等于空大。花了资源部署了就必须有用。


公司的监控信息是往企业微信群里发的。那个时候我翻了社区还没有 webhook 往企业微信群里发的案例(现在有了,感谢社区 https://tidb.net/blog/199877a0)


我当时采用的方式比较原始,就是 alertmanager.yml+ 微信告警的模板文件 tmpl。本来写的一大段,现在一看还不如上面这个好。就不献丑了。推荐用上面这个。


总之不管用什么方式,告警还是要弄好,有些重复 / 固定触发的(我这个 4 核 8g 的配置,tikv 内存超过 80% 的告警基本一直有,就算 tikv 挂了,不要 2 个小时也必出这个告警)可以设置一个长期的静默时间过滤掉不看,但告警不能没有。这是个原则问题。


发布于: 刚刚阅读数: 6
用户头像

TiDB 社区官网:https://tidb.net/ 2021-12-15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
tidb之旅——tidb架构选择_迁移_TiDB 社区干货传送门_InfoQ写作社区