NOSQL数据库浅析(一):Memcache 内存分配策略和性能(使用)状态检查
来源:互联网 发布:大学生在知乎怎么赚钱 编辑:程序博客网 时间:2024/05/21 10:07
前言:
一直在使用Memcache,但是对其内部的问题,如它内存是怎么样被使用的,使用一段时间后想看看一些状态怎么样?一直都不清楚,查了又忘记,现在整理出该篇文章,方便自己查阅。
1:参数
上面加粗的参数,需要重点关注,正常启动的例子:
可以通过命令查看所有参数:stats settings
2:理解memcached的内存存储机制
Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存以page为单位,默认情况下一个page是1M,可以通过-I参数在启动时指定,分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合),如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在重启前不会被回收或者重新分配,以解决内存碎片问题。
Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
Chunk
用于缓存记录的内存空间。
Slab Class
特定大小的chunk的组。
Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责一定范围内的数据存储。memcached根据收到的数据的大小,选择最适合数据大小的slab。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
如图所示,每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:100字节大小的字符串会被存到slab2(88-112)中,每个slab负责的空间是不等的,memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改-f参数来修改增长比例。
Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。chunk是memcached实际存放缓存数据的地方,这个大小就是管理它的slab的最大存放大小。每个slab中的chunk大小是一样的,如上图所示slab1的chunk大小是88字节,slab2是112字节。由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。这里需要注意的是chunk中不仅仅存放缓存对象的value,而且保存了缓存对象的key,expire time, flag等详细信息。所以当set 1字节的item,需要远远大于1字节的空间存放。
memcached在启动时指定 Growth Factor因子(通过-f选项), 就可以在某种程度上控制slab之间的差异。默认值为1.25。
slab的内存分配具体过程如下:
Memcached在启动时通过-m参数指定最大使用内存,但是这个不会一启动就占用完,而是逐步分配给各slab的。如果一个新的数据要被存放,首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如果没有则要进行申请,slab申请内存时以page为单位,无论大小为多少,都会有1M大小的page被分配给该slab(该page不会被回收或者重新分配,永远都属于该slab)。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,再从这个chunk数组中选择一个用于存储数据。若没有空闲的page的时候,则会对改slab进行LRU,而不是对整个memcache进行LRU。
以上大致讲解了memcache的内存分配策略,下面来说明如何查看memcache的使用状况。
3,memcache状态和性能查看
① 命中率 :stats命令
按照下面的图来解读分析
get_hits表示读取cache命中的次数,get_misses是读取失败的次数,即尝试读取不存在的缓存数据。即:
命中率=get_hits / (get_hits + get_misses)
命中率越高说明cache起到的缓存作用越大。但是在实际使用中,这个命中率不是有效数据的命中率,有些时候get操作可能只是检查一个key存在不存在,这个时候miss也是正确的,这个命中率是从memcached启动开始所有的请求的综合值,不能反映一个时间段内的情况,所以要排查memcached的性能问题,还需要更详细的数值。但是高的命中率还是能够反映出memcached良好的使用情况,突然下跌的命中率能够反映大量cache丢失的发生。
② 观察各slab的items的情况:Stats items命令
主要参数说明:
outofmemoryslab class为新item分配空间失败的次数。这意味着你运行时带上了-M或者移除操作失败number存放的数据总数age存放的数据中存放时间最久的数据已经存在的时间,以秒为单位evicted不得不从LRU中移除未过期item的次数 evicted_time自最后一次清除过期item起所经历的秒数,即最后被移除缓存的时间,0表示当前就有被移除,用这个来判断数据被移除的最近时间evicted_nonzero没有设置过期时间(默认30天),但不得不从LRU中称除该未过期的item的次数因为memcached的内存分配策略导致一旦memcached的总内存达到了设置的最大内存,表示所有的slab能够使用的page都已经固定,这时如果还有数据放入,将导致memcached使用LRU策略剔除数据。而LRU策略不是针对所有的slabs,而是只针对新数据应该被放入的slab,例如有一个新的数据要被放入slab 3,则LRU只对slab 3进行,通过stats items就可以观察到这些剔除的情况。
注意evicted_time:并不是发生了LRU就代表memcached负载过载了,因为有些时候在使用cache时会设置过期时间为0,这样缓存将被存放30天,如果内存满了还持续放入数据,而这些为过期的数据很久没有被使用,则可能被剔除。把evicted_time换算成标准时间看下是否已经达到了你可以接受的时间,例如:你认为数据被缓存了2天是你可以接受的,而最后被剔除的数据已经存放了3天以上,则可以认为这个slab的压力其实可以接受的;但是如果最后被剔除的数据只被缓存了20秒,不用考虑,这个slab已经负载过重了。
通过上面的说明可以看到当前的memcache的slab1的状态:
items有305816个,有效时间最久的是21529秒,通过LRU移除未过期的items有95336839个,通过LRU移除没有设置过期时间的未过期items有95312220个,当前就有被清除的items,启动时没有带-M参数。
③ 观察各slabs的情况:stats slabs命令
从Stats items中如果发现有异常的slab,则可以通过stats slabs查看下该slab是不是内存分配的确有问题。
主要参数说明:
这里需要注意:total_pages 这个是当前slab总共分配大的page总数,如果没有修改page的默认大小的情况下,这个数值就是当前slab能够缓存的数据的总大小(单位为M)。如果这个slab的剔除非常严重,一定要注意这个slab的page数是不是太少了。还有一个公式:
total_chunks = used_chunks + free_chunks + free_chunks_end
另外stats slabs还有2个属性:
属性名称属性说明
active_slabs
活动的slab总数total_malloced
实际已经分配的总内存数,单位为byte,这个数值决定了memcached实际还能申请多少内存,如果这个值已经达到设定的上限(和stats settings中的maxbytes对比),则不会有新的page被分配。
④ 对象数量的统计:stats sizes
注意:该命令会锁定服务,暂停处理请求。该命令展示了固定chunk大小中的items的数量。也可以看出slab1(96byte)中有多少个chunks。
⑤ 查看、导出key:stats cachedump
在进入memcache中,大家都想查看cache里的key,类似redis中的keys *命令,在memcache里也可以查看,但是需要2步完成。
一是先列出items:
stats items --命令......STAT items:29:number 228STAT items:29:age 34935...END
二是通过itemid取key,上面的id是29,再加上一个参数:为列出的长度,0为全部列出。
stats cachedump 29 0 --命令ITEM 26457202 [49440 b; 1467262309 s]...ITEM 30017977 [45992 b; 1467425702 s]ITEM 26634739 [48405 b; 1467437677 s]END --总共228个keyget 26634739 取value
如何导出key呢?这里就需要通过 echo ... nc 来完成了
echo "stats cachedump 29 0" | nc 10.211.55.9 11212 >/home/zhoujy/memcache.log
在导出的时候需要注意的是:cachedump命令每次返回的数据大小只有2M,这个是memcached的代码中写死的一个数值,除非在编译前修改。
⑥ 另一个监控工具:memcached-tool,一个perl写的工具:memcache_tool.pl。
./memcached-tool 10.211.55.9:11212 --执行 # Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 1 96B 20157s 28 305816 yes 95431913 0 0 2 120B 16049s 40 349520 yes 117041737 0 0 3 152B 17574s 39 269022 yes 92679465 0 0 4 192B 18157s 43 234823 yes 78892650 0 0 5 240B 18722s 52 227188 yes 72908841 0 0 6 304B 17971s 73 251777 yes 85556469 0 0 7 384B 17881s 81 221130 yes 75596858 0 0 8 480B 17760s 70 152880 yes 53553607 0 0 9 600B 18167s 58 101326 yes 34647962 0 0 10 752B 18518s 52 72488 yes 24813707 0 0 11 944B 18903s 52 57720 yes 16707430 0 0 12 1.2K 20475s 44 38940 yes 11592923 0 0 13 1.4K 21220s 36 25488 yes 8232326 0 0 14 1.8K 22710s 35 19740 yes 6232766 0 0 15 2.3K 22027s 33 14883 yes 4952017 0 0 16 2.8K 23139s 33 11913 yes 3822663 0 0 17 3.5K 23495s 31 8928 yes 2817520 0 0 18 4.4K 22611s 29 6670 yes 2168871 0 0 19 5.5K 23652s 29 5336 yes 1636656 0 0 20 6.9K 21245s 26 3822 yes 1334189 0 0 21 8.7K 22794s 22 2596 yes 783620 0 0 22 10.8K 22443s 19 1786 yes 514953 0 0 23 13.6K 21385s 18 1350 yes 368016 0 0 24 16.9K 23782s 16 960 yes 254782 0 0 25 21.2K 23897s 14 672 yes 183793 0 0 26 26.5K 27847s 13 494 yes 117535 0 0 27 33.1K 27497s 14 420 yes 83966 0 0 28 41.4K 28246s 14 336 yes 63703 0 0 29 51.7K 33636s 12 228 yes 24239 0 0
解释:
列含义#slab class编号Item_Size chunk大小Max_ageLRU内最旧的记录的生存时间pages分配给Slab的页数countSlab内的记录数、chunks数、items数、keys数Full?Slab内是否含有空闲chunkEvicted从LRU中移除未过期item的次数Evict_Time最后被移除缓存的时间,0表示当前就有被移除OOM-M参数?
4,总结
实际应用Memcached时,我们遇到的很多问题都是因为不了解其内存分配机制所致,希望本文能让大家初步了解Memcached在内存方便的分配机制,虽然redis等一些nosql的数据库产品在很多产品中替换了memcache,但是memcache还有很多项目会依赖它,所以还得学习来解决问题,后续出现新内容会不定时更新。
5,参考文档
Memcached内存分析、调优、集群
memcache内存分配、性能检测
memcached的基础
理解memcached的内存存储
memcached的删除机制和发展方向
memcached的分布式算法
memcached的应用和兼容程序
Memcached二三事儿
- NOSQL数据库浅析(一):Memcache 内存分配策略和性能(使用)状态检查
- Memcache 内存分配策略和性能(使用)状态检查
- Memcache 内存分配策略和性能(使用)状态检查
- Memcache 内存分配策略和性能(使用)状态检查
- Memcache内存分配策略
- Memcache内存分配策略
- Memcache内存分配策略
- Memcache内存分配策略
- NOSQL数据库浅谈(一):MemCache解读
- Memcache(MC)系列(六)Memcache内存分配策略
- NoSQL数据库浅析(一):Redis和Memcached
- NoSQL数据库memcache和redis区别()
- 垃圾回收和内存分配策略(一)
- Memcache内存分配策略 page chunk slat
- php 内存分配和检查
- 服务器数据库系列 - memcache内存分配
- NOSQL数据库浅析(三):redis的使用及配置
- 内存分配和回收策略
- 蓝牙HDP协议源码解析
- READING NOTE: YOLO9000: Better, Faster, Stronger
- ver0.83--preproc_data.m
- 瓦片地图
- 大数据学习笔记之十一 云计算应用分类
- NOSQL数据库浅析(一):Memcache 内存分配策略和性能(使用)状态检查
- linux系统maven安装笔记
- CSS 实现三角形对话框
- afinal----finalDB向数据库里save数据出错:sava error:sqlInfo is null
- Python连续赋值需要注意的地方
- 超星慕课2017中西文化专题比较期末考试答案题库
- Unity 小技巧
- Chapter 4: 序列式容器之 stack 和 queue
- rectNative安装