memcache的内存分配机制 |
前言:应用程序运行需要使用内存存储数据,但对于一个缓存系统来说,申请内存、释放内存将十分频繁,非常容易导致大量内存碎片,最后导致无连续可用内存可用,对于这种情况缓存系统不能接受。因此Memcached采用了Slab Allocator机制来分配、管理内存。
(1)Slab Allocator内存分配机制
Memcache按照预先规定的大小,将分配的内存分割成特定长度的块,以解决内存碎片问题。
Memcache的存储涉及到slab,page,chunk三个概念,三者是包含关系,从小到大如下:
-
Page:分配给Slab的内存空间,默认为1MB,分配后就得到一个Slab。Slab分配之后内存按照固定字节大小等分成chunk
-
Chunk:用于缓存记录kv值的内存空间。Memcached会根据数据大小选择存到哪一个chunk中,假设chunk有128bytes、64bytes,数据只有100bytes存储在128bytes中,存在些浪费。
Chunk最大就是Page的大小,即一个Page中就一个Chunk -
Slab Class:Slab按照大小分组,就组成不同的Slab Class
slab class图示:
示例:如果有100bytes要存,那么Memcached会选择上图中Slab Class 2存储,因为它是120bytes的Chunk。
综上所述:将memcache可以使用的内存按照一定规律进行切片,切完之后的内存空间可以形象的看做快递柜,然后往其中每个’快递柜’中放置key-value,其中存放key-value的单位为’chunk’,当’快递柜’格子被占满时,将按照最近最少使用算法就行相应的覆盖放置。
Slab之间的差异可以使用Growth Factor控制,默认1.25。
(2)懒过期Lazy Expiration
memcached不会监视数据是否过期,而是在取数据时才看是否过期,过期的把数据有效期限标识为0,并不清除该数据。以后可以覆盖该位置存储其它数据。
(3)LRU
当内存不足时,memcached会使用LRU(Least Recently Used)机制来查找可用空间,分配给新纪录使用
memcache的使用 |
(4)比较重要的几个启动参数
**-f:**增长因子,chunk的值会按照增长因子的比例增长(chunk size growth factor).
**-n:**每个chunk的初始大小(minimum space allocated for key+value+flags),chunk大小还包括本身结构体大小.
**-I:**每个slab page大小(Override the size of each slab page. Adjusts max item size)
**-m:**需要分配的大小(max memory to use for items in megabytes)
-u username memcached运行的用户身份,必须普通用户
-p 绑定的端口,默认11211
-m num 最大内存,单位MB,默认64MB
-c num 最大连接数,缺省1024
-d 守护进程方式运行
-f 增长因子Growth Factor,默认1.25
-v 详细信息,-vv能看到详细信息
-M 内存耗尽,不许LRU
-U 设置UDP监听端口,0表示禁用UDP
(5)Slab Allocator 的缺点
由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100 字节的数据缓存到128 字节的chunk 中,剩余的28字节就浪费了,对于该问题目前还没有完美的解决方案,但是可以通过分析目标应用缓存的大小,来调整chunk的大小以减少浪费。
memcached 在启动时指定Growth Factor因子(通过f选项),就可以在某种程度上控制slab之间的差异。默认值为1.25,可以对存储的key-value进行数据统计大小分析,然后制定合理的Growth Factor因子(没办法,要合理使用内存嘛),一般情况下使用缺省的Growth Factor因子。
(6)memcache启动:
~]# memcached -u memcached -p 11211 -f 1.25 -vv
slab class 1: chunk size 96 perslab 10922
slab class 2: chunk size 120 perslab 8738
slab class 3: chunk size 152 perslab 6898
slab class 4: chunk size 192 perslab 5461
slab class 5: chunk size 240 perslab 4369
slab class 6: chunk size 304 perslab 3449
slab class 7: chunk size 384 perslab 2730
slab class 8: chunk size 480 perslab 2184
slab class 9: chunk size 600 perslab 1747
slab class 10: chunk size 752 perslab 1394
slab class 11: chunk size 944 perslab 1110
slab class 12: chunk size 1184 perslab 885
slab class 13: chunk size 1480 perslab 708
slab class 14: chunk size 1856 perslab 564
slab class 15: chunk size 2320 perslab 451
slab class 16: chunk size 2904 perslab 361
slab class 17: chunk size 3632 perslab 288
slab class 18: chunk size 4544 perslab 230
slab class 19: chunk size 5680 perslab 184
slab class 20: chunk size 7104 perslab 147
slab class 21: chunk size 8880 perslab 118
slab class 22: chunk size 11104 perslab 94
slab class 23: chunk size 13880 perslab 75
slab class 24: chunk size 17352 perslab 60
slab class 25: chunk size 21696 perslab 48
slab class 26: chunk size 27120 perslab 38
slab class 27: chunk size 33904 perslab 30
slab class 28: chunk size 42384 perslab 24
slab class 29: chunk size 52984 perslab 19
slab class 30: chunk size 66232 perslab 15
slab class 31: chunk size 82792 perslab 12
slab class 32: chunk size 103496 perslab 10
slab class 33: chunk size 129376 perslab 8
slab class 34: chunk size 161720 perslab 6
slab class 35: chunk size 202152 perslab 5
slab class 36: chunk size 252696 perslab 4
slab class 37: chunk size 315872 perslab 3
slab class 38: chunk size 394840 perslab 2
slab class 39: chunk size 493552 perslab 2
slab class 40: chunk size 616944 perslab 1 #有内存浪费
slab class 41: chunk size 771184 perslab 1 #有内存浪费
slab class 42: chunk size 1048576 perslab 1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 212992, now 268435456
<29 send buffer was 212992, now 268435456
<28 server listening (udp)
<29 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
==> 预创建了这些slab class,按照增长因子1.25创建至1M一个,不够使用再创建划分至相同slab class下,memcache默认使用内存64M。
(7)与memcached通信的不同语言的连接器
- libmemcached提供了C库和命令行工具。
# yum list all | grep memcached
memcached.x86_64 1.4.15-10.el7_3.1 @base
libmemcached.i686 1.0.16-5.el7 base
libmemcached.x86_64 1.0.16-5.el7 base
libmemcached-devel.i686 1.0.16-5.el7 base
libmemcached-devel.x86_64 1.0.16-5.el7 base
memcached-devel.i686 1.4.15-10.el7_3.1 base
memcached-devel.x86_64 1.4.15-10.el7_3.1 base
opensips-memcached.x86_64 1.10.5-4.el7 epel
php-ZendFramework-Cache-Backend-Libmemcached.noarch
php-pecl-memcached.x86_64 2.2.0-1.el7 epel
python-memcached.noarch 1.48-4.el7 base
uwsgi-router-memcached.x86_64 2.0.17.1-2.el7 epel
(8)memcache协议:
- 查看/usr/share/doc/memcached-1.4.15/protocol.txt
add mykey 1 60 4
keyname flags 存活时间 多少字节
add key flags exptime bytes , 增加key,过期时间为秒,bytes为存储数据的字节数
参考: https://www.jianshu.com/p/0e7629401a2e