memcached的slab钙化问题

发布时间 2023-03-24 17:07:02作者: Justtosee

memcached的slab钙化问题

现象:

服务某些接口成功率波动,经研发查看是数据在memcached查询的偶尔失败。

因为前一晚升级的时候,改了存储在memcahed的数据(图片base64)的大小,改成高清图。

猜测是memcached存储有问题

排查步骤:
查看memcached监控

 

 

 内存使用率一直都是满的,这个是之前就存在的问题。

 

 

 数据命中率波动,是服务接口报错的表面原因。

接着上memcached服务器查看stats状态,看看是那些数据导致命中率下降

使用memcached-tool工具

 

 

 可以看出大item_size的存储数量很少,就1个,而且保留时间都很短,几秒中就被更新了。

推断是这部分数据的查询导致命中率下降。

那为啥明明是刚写入比较新的数据,但被淘汰了?

经百度查询是Slab钙化问题:

memcached内存利用率一直是90%,已经达到growth factor=1.25的期望内存利用率,所以内存已满。

就算flush_all删除所有数据,item仍占用chunk size,MC删除机制是数据不会真正从内存中消失,只要被其他数据覆盖,MC不会主动删除Slab chunk已存在的数据。

MC淘汰策略是淘汰相同的Slab class数据,96B的item也不会重新使用192B的chunk size,只会使用原有启动Memcached时分配的1MB Slab class(Chunk size 96B),这就是所谓的Slab钙化问题。
假设Slab有各种规格(64~ 1M字节),比如应用存入的大部分数据大小在 64 ~ 128 字节范围内,那么这些数据会存储在128个字节大小的Slab chunk中,这些Slab chunk以链表的方式连接在一起。当已经没有空余的内存分配新的Slab,如果这时候写入10K新数据,且之前并没有这么大的数据写入时,那么这条新数据可以写入成功。但是当下次再写入10K数据时,第一次写入的10K数据就会被逐出。当下一次写入的新数据在64 ~ 128字节时,128字节大小的Slab链表上的数据会以LRU方式淘汰,所以LRU只会淘汰同一级别的Slab数据。

Slab钙化降低内存使用率,如果发生Slab钙化,有三种解决方案:

1) 重启Memcached实例,简单粗暴,启动后重新分配Slab class,但是如果是单点可能造成大量请求访问数据库,出现雪崩现象,冲跨数据库。

2) 随机过期:过期淘汰策略也支持淘汰其他slab class的数据,twitter工程师采用随机选择一个Slab,释放该Slab的所有缓存数据,然后重新建立一个合适的Slab。

3) 通过slab_reassign、slab_authmove参数控制。

============================================================================================================

Memcached 内存分配机制介绍

https://cloud.tencent.com/developer/article/1981648

============================================================================================================

memcached-tool使用详解

memcached-tool脚本可以方便地获得slab的使用情况 (它将memcached的返回值整理成容易阅读的格式),可以从下面的地址获得脚本:
http://www.netingcn.com/demo/memcached-tool.zip

使用方法也极其简单:

Usage: memcached-tool <host[:port]> [mode]

memcached-tool 10.0.0.5:11211 display # shows slabs
memcached-tool 10.0.0.5:11211 # same. (default is display)
memcached-tool 10.0.0.5:11211 stats # shows general stats
memcached-tool 10.0.0.5:11211 move 7 9 # takes 1MB slab from class #7

各列的含义:
# slab class编号
Item_Size Chunk大小
Max_age LRU内最旧的记录的生存时间
1MB_pages 分配给Slab的页数
Count Slab内的记录数
Full? Slab内是否含有空闲chunk

============================================================================================================

memcached使用详解

https://zhuanlan.zhihu.com/p/46364634