写点什么

我的内存去哪儿了?

作者: TiDBer_jYQINSnf 原文来源:https://tidb.net/blog/3ee22746

背景:

今天有一个 tidb 用户反馈,为什么我的内存还没用到节点的规格(64G) 就 OOM 了。


我们的环境是基于 K8S 部署的



带着这个问题做了一番搜索,总算是能回答用户的问题了。

1. 监控面板的内存值是怎么来的:

首先看这个面板指标的定义:


avg(process_resident_memory_bytes{k8s_cluster="$k8s_cluster", tidb_cluster=~"$tidb_cluster.*", component=~".*tikv"}) by (instance)


tikv 这个指标采集的内容:




tikv 的内存计算方式:


1. 从 /proc/self/stats 里获取 rss 字段,是进程实际在内存中使用占用的页数


2. 拿这个页数乘以 PageSize,计算出字节数


也就是说这个值只计算了 TiKV 自己进程用的内存。

2. k8s 是根据什么值进行 OOM kill 的?

经过搜索得到 k8s 会依据 container_memory_working_set_bytes 值去 OOMKilled pod


那么 container_memory_working_set_bytes 的值都包括什么?


从网上借一个图,因为 tikv 不是 java 程序,所以没有 JVM 内存



那么关键问题就在于 k8s 把 cache file 计算在内是不是合适?


关于这个的讨论 issue 如下:


https://github.com/kubernetes/kubernetes/issues/43916

3. cache 的内存到底对 tikv 有没有用?

既然无法改变 k8s oom kill 的行为,那么 cache 的这些文件该不会全是 tikv 写的 log 吧?到底对 tikv 的 io 加速有没有用呢?


又找到了一个 vmtouch 工具。


根据 vmtouch 的结果查看:


总共缓存了 27G 的数据:



其中 raft-engine 的 raftlog 占了 6G



rocksdb 的 sst 文件占用了 19G



这两部分占了大头。


tikv 是 raft 3 副本的,按 tikv 的写逻辑:


数据首先写入 raft-engine,在写入的同时向其他 2 节点同步 raft-log, raft-log 同步完后 apply 进 kv-db. 一般情况下, raft-log 不会再从磁盘读,但是如果要新加一个 raft-peer ,就需要拿 raft-log + kv-db 中的数据向新的 peer 同步数据,这 6G 的作用不是那么明显。


但是 raft log 随着都 apply 进 kv-db, 也会不断的 gc,也就是说写入量不那么大的情况下,这些文件会比较少,文件被删掉的话自然这些内存就释放出来了。


另外一部分: rocksdb 的 sst 文件缓存有没有用呢?


根据 rocksdb 的原理,数据首先写入 memtable,然后 flush 到磁盘, 形成 sst 文件,标记为 level0 层的文件,然后这些 sst 会在 compact 到下一层的时候读取一遍,然后合并成新的文件,老的 sst 就删掉了。也就是说缓存的文件大概率会在 compact 的时候用到。这样说的话,内存也没浪费,即使没有 compact ,文件缓存到内存中,查询数据的时候也会用到。

结论:

由此可以得出结论,64G 的内存几乎全部服务于 tikv 的读写数据,是有一些浪费,但是也没那么严重。业务方不能说我们少给内存了😜。


参考:


http://mysql.taobao.org/monthly/2020/09/01/


https://blog.csdn.net/u010657094/article/details/138510248


https://github.com/kubernetes/kubernetes/issues/43916


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

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

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

评论

发布
暂无评论
我的内存去哪儿了?_监控_TiDB 社区干货传送门_InfoQ写作社区