一篇文章彻底搞懂 TiDB 集群各种容量计算方式
背景
TiDB 集群的监控面板里面有两个非常重要、且非常常用的指标,相信用了 TiDB 的都见过:
Storage capacity:集群的总容量
Current storage size:集群当前已经使用的空间大小
当你准备了一堆服务器,经过各种思考设计部署了一个 TiDB 集群,有没有想过这两个指标和服务器磁盘之间到底是啥关系?
反正我们经常被客户问这个问题,以前虽然能说出个大概,总体方向上没错,但是深究一下其实并不严谨,这次翻了源码彻底把这个问题搞清楚。开始之前再卖一个关子,大家可以看看自己手上的集群监控有没有这种情况:
TiKV 实例的已用空间(store size)+ 可用空间(available size) ≠ 总空间(capacity size)
盘越大越明显。
再仔细点看,监控上显示的总容量大小和 TiKV 实例所在盘大小也不匹配。
是不是有亿点意外。
结论先行
PD 监控下的
Storage capacity
和Current storage size
来自各个 store 的累加,这里 store 包含了 TiKV 和 TiFlashCurrent storage size
包含了多个数据副本(TiKV 和 TiFlash 的所有副本数),非真实数据大小TiKV 实例容量统计的是 TiKV 所在磁盘的整体大小与
raftstore.capacity
参数较小的值,同时监控用的 bytes(SI) 标准显示,就是说不是用 1024 做的转换而是 1000,所以和df -h
输出的盘大小有差距TiKV 实例的已用空间只统计了
data-dir
下的部分目录,非整个data-dir
或整块盘基于前两条,可用空间也就不等于总空间减去已用空间了
看到的现象
本文描述的内容基于以下集群:
各节点磁盘情况(来自 TiDB Dashboard 统计):
在此之前,我一直以为 PD 监控面板下的集群总空间是 PD 读取了所有 TiKV+TiFlash 实例部署盘的累计大小,所以我尝试把上图的 4 个存储节点的磁盘容量相加发现并不等于集群总容量(文章开头的图片有显示),差了 100 多个 G:
Dashboard 上 4 个存储节点磁盘容量均为 475.8G,累计容量 475.8G * 4 = 1903.2G
Grafana 显示的单个 TiKV 实例:510.9G,总空间:2.04 T
再和操作系统显示的磁盘容量对比,发现能和 Dashboard 显示的对应上:
但仔细看容量单位的区别,发现 Dashboard 显示的是GiB
,Grafana 显示的是GB
,两者是有区别的。尝试在系统中用GB
显示磁盘大小:
这里输出的 511G 能和 Grafana 监控对应上,同时按 4 个 511G 的存储节点计算也能和总容量对应上。
但是用同样的方法并不能解释 TiKV 已用空间的偏差问题,检查结果如下:
总结一下看到的现象:
Dashboard 上显示的 TiKV 盘大小(GiB)是实际部署盘的总大小,Grafana 也是部署盘的总大小但单位是 GB
Grafana 集群总容量是所有存储节点部署盘的累计大小(GB)
TiKV 实例已用空间大小计算方式未知(要搞清楚只能扒源码了)
不同进制转换带来的影响
这里简单提一下GB
和GiB
的区别,帮助大家理解。
GB 是按 10 进制来转换,也就是说 1GB=1000MB,市面上厂商宣传的大小都是 10 进制,可理解为商业标准
GiB 是按 2 进制来转换,也就是说 1GiB=1024MiB,计算机系统只认这个,可理解为事实标准
那么当你买了一台 128G 存储的手机,实际使用中会发现空间“缩水”了,U 盘、硬盘等也类似。
与这两个进制差异有关的还有两个行业标准,即byte(SI)
和byte(IEC)
,感兴趣的可以去查一下历史,这里只需要知道:
byte(SI)
对应十进制byte(IEC)
对应二进制
Grafana 里面可以使用编辑监控面板调整显示单位,例如:
如果把单位统一的话,前 2 个现象就很好解释了。
但需要注意的是,在 Grafana 中并不是所有面板都采用了byte(SI)
,甚至同一个指标也出现不同面板显示的单位不一样,比如 Overview 下面的 TiDB 分组内存面板使用十进制,System Info 分组内存面板使用二进制,用的时候要小心。
TiKV 的数据文件
要搞清楚 TiKV 的已用空间是怎么计算的,先提一下 TiKV 相关的数据文件。大家都知道 TiKV 底层用的 RocksDB 作为持久层,并且 raft 日志和实际数据分别对应一个 RocksDB 实例,那么看看 TiKV 的数据目录到底放了啥东西,以前面的集群为例:
几类文件解读一下:
db 目录,这是最终数据的存放目录,
db
在源码中写死无法修改rocksdb[-xxx-xxx].info 文件,数据 RocksDB 实例的日志文件,已经按日期归档好的可手动删除
raft-engine 目录,这是 raft 日志存放目录,受参数
raft-engine.dir
控制,没有开启 Raft Engine 特性时名称默认为raft
,受参数raftstore.raftdb-path
控制raftdb[-xxx-xxx].info 文件,raft 日志 RocksDB 实例的日志文件,已经按日期归档好的可手动删除
snap 目录,快照数据存放目录
import 目录,看名字是和导入相关,具体什么作用未知
space_placeholder_file 文件,预留空间的临时文件(TiKV 磁盘告警救急用,磁盘越大这个文件越大),相关参数
storage.reserve-space
last_tikv.toml 和 LOCK 文件,看名字猜测就行
从前面的观察来看,被监控统计到的 TiKV 已用空间比整个数据目录要小,那么可以推测出只统计了数据目录下的部分文件或目录,具体是哪些就要从源码里寻找答案。
Show Me The Code
TiDB 的监控数据分为两类,一类是服务器环境信息(CPU、内存、磁盘、网络等),一类是 TiDB 运行指标(Duration、QPS、Region 数、容量等)。前者通过与 Prometheus 配套的标准探针采集,即node_exporter
和black_exporter
,后者通过在源码中类似埋点方式采集数据然后由 Prometheus 来拉取。
以集群总容量这个指标入手,看看在源码中它是如何采集的。对应的公式:
用关键字storage_capacity
去 PD 源码里搜索找到如下代码:
数据来自storeStatistics
的StorageCapacity
字段,根据引用关系继续往上翻:
从这里可以看出总容量(Storage capacity)和总已用空间(Current storage size)都是从各个 store 累加得来,并不是 pd 直接从存储节点计算。
继续看GetCapacity()
是如何实现:
这里rawStats
是一个pdpb.StoreStats
类型,引用了另一个仓库:https://github.com/pingcap/kvproto 。最终实现为:
从调用关系来看,说明 PD 采集的数据都是来自 TiKV 上报(heartbeat)。继续追踪 TiKV 源码,以 heartbeat 为突破口:
这里的stats
正是一个pdpb::StoreStats
类型,我们想要分析的 3 个指标都在这,继续看他们的出处collect_engine_size()
:
核心逻辑分析都写在注释里,值得认真一看!
以为扒到这里就 happy ending 了,但是偶然又发现了另一个方法让我陷入沉思:
init_storage_stats_task
在 tikv 启动时被调用,就是说这是几个指标在初始化时的计算方式,整体逻辑与 heartbeat 上报并无区别,但已用空间计算方式有轻微差异:
space_placeholder_file 被算进去了
如果 raft engine 使用了单独的部署目录(代码里叫 path_in_diff_mount_point),那么 raft 日志的大小是不算在 tikv 已用空间内的
看起来前后计算不一致,但是由于 heartbeat 是持续更新的,最终是以 heartbeat 上报的为准。
这个差异准备提 issue 问问看。
PD 源码仓库:https://github.com/tikv/pd
TiKV 源码仓库:https://github.com/tikv/tikv
结尾
结论已经在文章开头给出了,希望大家看了本文都能对 TiDB 集群的各种空间计算有了清晰的认识。
本文只讨论的 TiKV 的容量计算细节,TiFlash 的计算方式也类似,我对比了 TFlash 的数据目录大小和监控显示已用大小 10 多 G 的差距,应该也是只计算了部分目录,但是总容量还是算的整块盘。不太熟悉 c++,留给其他大佬去探索吧🤣。
作者介绍:hey-hoho,来自神州数码钛合金战队,是一支致力于为企业提供分布式数据库 TiDB 整体解决方案的专业技术团队。团队成员拥有丰富的数据库从业背景,全部拥有 TiDB 高级资格证书,并活跃于 TiDB 开源社区,是官方认证合作伙伴。目前已为 10+ 客户提供了专业的 TiDB 交付服务,涵盖金融、证券、物流、电力、政府、零售等重点行业。
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/4d3ad8aa4be515ac34d9a69f9】。文章转载请联系作者。
评论