Memcached有一套自己的内存管理方式,而不是每次需要内存的时候就malloc,释放的时候就free。【slab=page】
为了提高效率,它使用预申请和分组的方式管理内存空间。
Memcached使用slab->chunk的组织方式管理内存。
Slab可以理解为一个内存块,一个slab是memcached一次申请内存的最小单位,在memcached中,一个slab的大小默认为1048576字节(1MB),
所以memcached都是整MB的使用内存。
每一个slab被划分为若干个chunk,每个chunk里保存一个item,每个item同时包含了item结构体、key和value(注意在memcached中的value是只有字符串的)。
slab按照自己的id分别组成链表,这些链表又按id挂在一个slabclass数组上,整个结构看起来有点像二维数组。
page一旦被分配在重启前不会被回收或者重新分配。
Memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改-f参数来修改增长比例。
如果一个新的缓存数据要被存放,memcached首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;
如果没有则要进行申请。slab申请内存时以page为单位,所以在放入第一个数据,无论大小为多少,都会有1M大小的page被分配给该slab。
申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,在从这个chunk数组中选择一个用于存储数据。
---------------------------------------------------------
id为0的slab,每chunk大小1字节,id为1的slab,每chunk大小2字节,id为2的slab,每chunk大小4字节……id为20的slab,每chunk大小为1MB,就是说id为20的slab里只有一个chunk
slab后一个的大小是前一个的1.25倍,chunk的大小是,在下一个slab中的chunk大小是前一个slab大小的2倍。
Memcached在启动时通过-m指定最大使用内存,但是这个不会一启动就占用,是随着需要逐步分配给各slab的。
Memcached单进程最大使用内存为2G,要使用更多内存,可以分多个端口开启多个Memcached进程
最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250控制
-----------------------------------------------------
单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576进行控制,它是默认的slab大小。
最大同时连接数是200,通过 conn_init()中的freetotal进行控制,最大软连接数是1024,通过settings.maxconns=1024 进行控制。
Memcached服务器端没有分布式功能,这完全取决于客户端的实现。
-----------------------------------------------------
二、启动参数:
-p 使用端口,默认11211。
-m 最大内存大小,默认64M。
-vv 用very verbose模式启动,调试信息和错误输出到控制台。
-d 作为daemon在后台启动。
Page – 分配给Slab的内存空间,默认是1MB,分配给Slab之后跟据Slab大小切分成chunk。
Chunk – 用于缓存数据的内存空间。
Slab Class – 特定大小的chunk组。
-------------------------------------------------------------
分布式hash算法:
(1)取模:
求得键整数的hash值,除以服务器台数,所得的余数决定服务器。
缺点:当添加或者移除服务器时,缓存重组的代价相当巨大,会影响缓存命中率。
(2)Consistent Hashing:
首先求出memcached节点的哈希值,并将其配置到0--2^32的圆上。然后用同样的方法求出存储数据的键的hash值,并映射到圆上。然后从存储数据映射的位置顺时针查找,将数据保存到找到的第一个服务器上。Consistent Hashing最大程度的抑制了键的重新分布,只有从增加服务器地点到逆时针相邻第一台服务器之间的键会受到影响。只需要把新增服务器的下一台服务器上的数据进行重新映射,就可以实现服务器的增加了。