• Memcached---Slab钙化问题


    一、引言

      Memcached采用LRU(Least Recent Used)淘汰算法,在内存容量满时踢出过期失效和LRU数据,为新数据腾出内存空间不过该淘汰算法在内存空间不足以分配新的Slab情况下,这时只会在同一类Slab内部踢出数据即当某个Slab容量满,且不能在内存足够分配新的Slab,只会在相同Slab内部踢出数据,而不会挪用或者踢出其他Slab的数据。这种局部剔除数据的淘汰算法带来一个问题:Slab钙化

    二、实践

    1 搭建一个64M、growth factor=1.25的MC节点。

    2 用item数据写满MC 192B的chunk,因为已经有evicted数量,所以192B chunk肯定已经写满,如图1所示。

     图1 memcached-tool结果

    3 计算内存利用率:bytes(59066176)/limit_maxbytes(67108864)=88%,已经达到growth factor=1.25的期望内存利用率,MC期望内存利用率计算方法请参考拙作《期望内存利用率计算方法》,所以内存已满,如图2所示。

    图2 stats结果

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

    图3 memcached-tool结果

    5 再用5万个96B的item写入MC,一共写50000*96B/1024/1024=4M数据,远远小于64M,但是只能写入96B*10922=1MB,即只能写一个Page,还是有很多96B的item被Evicted,如图4所示。

      即使192B的chunk数据已经被清除,MC淘汰策略是淘汰相同的Slab class数据,96B的item也不会重新使用192B的chunk size,只会使用原有启动Memcached时分配的1MB Slab class(Chunk size 96B),这就是所谓的Slab钙化问题。

     

    图4 memcached-tool结果 

    三、Slab钙化导致的问题

      Slab钙化降低内存使用率。

    3.1 为什么我写入比较新的数据,但被淘汰了?

      假设Slab有各种规格(64~ 1M字节),比如应用存入的大部分数据大小在 64 ~ 128 字节范围内,那么这些数据会存储在128个字节大小的Slab chunk中,这些Slab chunk以链表的方式连接在一起。当已经没有空余的内存分配新的Slab,如果这时候写入10K新数据,且之前并没有这么大的数据写入时,那么这条新数据可以写入成功。但是当下次再写入10K数据时,第一次写入的10K数据就会被逐出。当下一次写入的新数据在64 ~ 128字节时,128字节大小的Slab链表上的数据会以LRU方式淘汰,所以LRU只会淘汰同一级别的Slab数据。

    四、Slab钙化解决

    如果发生Slab钙化,有三种解决方案:

    •  重启Memcached实例,简单粗暴,启动后重新分配Slab class,但是如果是单点可能造成大量请求访问数据库,出现雪崩现象,冲跨数据库。
    • 随机过期:过期淘汰策略也支持淘汰其他slab class的数据,twitter工程师采用随机选择一个Slab,释放该Slab的所有缓存数据,然后重新建立一个合适的Slab。
    • 通过slab_reassign、slab_authmove参数控制。

    五、参考文章

      https://www.jianshu.com/p/b91a45711460

    本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/15075416.html

  • 相关阅读:
    盒子模型
    flex布局
    less基本使用
    vue全局配置(引入全局方法样式、按需加载elementui)
    vue性能优化
    vue实现原理
    webapi读取配置文件内容
    命令行启动dotnet core项目
    Linux常用命令
    sqlserver数据库密码忘记了,如何重置?
  • 原文地址:https://www.cnblogs.com/MrLiuZF/p/15075416.html
Copyright © 2020-2023  润新知