作者: 有猫万事足 原文来源: https://tidb.net/blog/26695303
前言
在我的设想里面,我应该不会这么早用到这个特性,原因很简单,整个TiDB集群根本不涉及多租户的使用场景。 应该说目前TiDB集群中的用户就2个:dmuser用户负责把上游mysql写入流量接入tidb集群;biuser只有只读权限配置到了metabase里面,给metabase查询用。 即便是我要用到这个特性,也应该是在有一天真的使用tidb集群替换上游的多套mysql之后。那个时候是个典型的多租户使用场景。 然而,首先让我对这个特性感兴趣的原因是RU。
RU
资源管控的基本单位是RU。 https://docs.pingcap.com/zh/tidb/stable/tidb-resource-control#%E4%BB%80%E4%B9%88%E6%98%AF-request-unit-ru
Request Unit (RU) 是 TiDB 对 CPU、IO 等系统资源的统一抽象的计量单位,用于表示对数据库的单个请求消耗的资源量。请求消耗的 RU 数量取决于多种因素,例如操作类型或正在检索或修改的数据量。
如果让我说RU好在哪里,首先就好在RU是抽象的。
看看我这个4核8g乞丐版集群的监控吧。
接入上游mysql写入流量后,cpu一直不怎么高,除非执行大表的导入。但tikv的内存一直不低,tikv内存超80%的告警一直在。所以我干脆设置了一个长达1年的静默期忽略了它。io图的单位不是百分比,我看对应的数值很难评估当前io离极限有多远。
那问题来了,当老板问我,我准备上游再切10台同样mysql进TiDB集群,你的集群能抗的住吗?
我该怎么回答他呢?这3项指标有高有低,甚至有些本菜鸡都没有量化的标准。我敢说——行,放马过来;或者:不行,得加钱吗?
以上这个情况是我不能接受的。
经过抽象的RU却可以解决我的问题。我现在已经接入了10+套上游的mysql写入流量。
因为dmuser基本都是写入操作,我只要进入资源管控界面,看下预估的oltp_write_only RU是多少,再看看当前的RU是多少就可以回答老板的问题了。
对于我这种非专业人士,我不需要关注cpu,内存,io。这些太专业,太具体。也许有朝一日,我可以成为大佬靠这些指标来更加准确的评估集群的负载,但不是现在。
资源管控界面显示,预估oltp_write_only RU是3w6,当前是800.我可明确的告诉老板,再来10套绝对没有问题。
非专业人士使用预估oltp_write_only RU/oltp_read_only RU,再结合当前实际的RU消耗量,来评估集群的读写负载,可能是比cpu,内存,io这些更加直观的。
正是在这种对比下,我才确认当前的TiDB集群负载很低——即便某些节点内存占用高。
那下一个问题就是这个oltp_write_only RU的评估准确吗?
尝试通过负载校准
通过负载校准RU需要一定的负载。
想想我之前一导入大表,tikv就轮流挂的'盛况'。来点负载根本不是事,安排。
于是在我执行了一个大表导入后,
校准的值比预估高一些
但是付出的代价也是触目惊心的
负载校准的值是比实际要高一些,不过从tikv的表现来看,它更像是在警告我,最好不要跑到这么高的RU。
听人劝吃饱饭,改。
给dmuser添加资源管控
tikv的内存告警一直是让我觉得战战兢兢的原因。而tikv也经常用实际行动告诉我,4核8g这个乞丐版的配置对tikv来说是不靠谱的。
经过上面的测试,我决定还是按照预估的数字36000RU来设置dmuser这个偏向写的用户的RU上限,负载校准后的值是比这个高,但代价是不稳定,这就没有办法采纳了。
CREATE RESOURCE GROUP max_write_rg RU_PER_SEC = 36000 PRIORITY = MEDIUM;
BURSTABLE参数不采用。原因同样是集群的稳定,我怕临时BURSTABLE一下,tikv又挂了。
绑定dmuser到这个资源组。
ALTER USER dmuser RESOURCE GROUP max_write_rg;
因为绑定后只对新建会话有用,干脆重启一下角色为tidb的节点
tiup cluster restart -R tidb
再执行导入,4核8g的配置,cpu最高也就在350%左右徘徊,不会再跑到380%以上去了。
执行导入的时候对读取任务也没有任何影响。
可以看到导入开始,写流量和读流量就变成两条平行线。中途有读取进来的时候,读流量会快速越过写流量,但写流量不会有任何抖动。有序,多么美妙。
在导入期间的database time拆解如下:
可以看到dm大表导入任务相关的replace和commit耗时明显变长。其他读取相关的操作时间也变长了一些,但绝对在可以接受的范围内。delete和update耗时也在可以接受的范围,说明其他进入到sync环节的dm同步任务并没有受到显著的影响。
既然看上去稳定多了,就该浪一点了。
上一篇完成了生成列的改造,上游10+个库的日志表都需要全部重新导一遍。7.1版本之前我反复提醒:大表的导入task最好是错开执行,那现在就多起几个大表的导入task看看。把task中的pool-size调回默认值。不特别关注该参数设置。起多个task。观察tikv一直稳定运行,再也没有发生tikv轮流挂的情况。
事实上,自从将dmuser加入资源管控之后,即使是我这个乞丐版的4核8g配置的tikv也再没有挂过。一直稳定运行到现在。
资源管控的问题
从我粗浅的认知来说:资源管控的问题在于,读写RU不能分开限制
从某种程度上,我觉得资源管控对我的系统稳定性的贡献这么大,完全是因为在当前这个场景下,我的读写用户是完全分离的。 我可以根据oltp_write_only估算的RU数量给dmuser设置资源组。 我还可以根据oltp_read_only估算的RU数量给biuser设置资源组。 这两个组都能确保各自RU的用量不会超过他们各自实际行为的上限。 哪怕我能看到如下这个提示信息,
而实际使用过程中,集群的稳定,确实是被资源管控有力的保证了。
但如果以后从mysql完全转向TiDB,情况就会变得复杂,每个游戏服执行的是读写混合负载。 当前集群读写RU并不均衡,读只有7000,而写是3w6000. 我估计到时候我只能设置一个7000RU的资源组取读写这两者的最小值,作为混合负载的用户的资源组。 当然这个判断是武断的,因为我的集群实际已经是生产系统了,我也没想出更好的混合负载测试方案。 这方面我还要多学习其他大佬的资源组设置方式。
后记
从4月开始有想法,到目前基本改造完成,对数据库再无任何数据获取死角。 大部分统计都可以在10s以内获得结果——在没有资源上tiflash的情况下。如果业务人员对这个结果有任何疑问,只要慢慢去掉聚合的维度和聚合的函数,就可以直接追踪到原始记录。 这个上钻/下钻的过程是流畅的。因为不会影响上游生产环境,可以大胆的鼓励业务人员在数据中探索。 从mysql迁移到TiDB的过程也是愉快的。 全部使用4核8g来组成这个集群,也来我自己对于分布式系统的一个根深蒂固的认知。 即,分布式系统从诞生的第一天起,就不是为了让更大马才能拉更大的车。它从诞生的第一天起,解决的问题就是蚂蚁如何咬死象。 虽然有点运气的因素——7.1版本恰好发布了资源管控特性,保证了集群资源不足时的稳定性。 但这也同时证明了,TiDB是一个好的分布式系统。 好的分布式系统就应该能应付这种情况。 TiDB证明了自己。也证明了我的选择没有错。