序:前几天写了一篇关于MemCached使用的一篇总结《 Memcached研究》
今天主要谈谈使用MemCached的一些深入的东西,源于一问题的思考,我主要谈谈Memcache的结构、服务端数据存储规则。
一个问题
这样的,公司的验证码数据和一个参数类A(新加的,以前那台服务器基本上就存验证码信息)序列化后放进了同个memcached服务器。这个系统上线后呢,就出现一个问题:
1. 在测试服务器上(环境与正式相同,使用的数据库都是相同的,唯一的不同是缓存服务器),程序正常执行,没有问题。
2. 上线后,在高峰期发现:参数类A无法写进缓存服务器。
3. 没招的情况下,重启memcached服务,又好了一阵,然后出现2错误。
问题分析:
初步认为,是memcached存数据出了问题。先前对memcached的认识:数据满了时,新的数据会替换掉过期的数据;如果没有过期数据,就会挤掉在memcached里面保存最久的数据。
基于这种认识,就会感到奇怪:充其量是取不到数据,怎么会无法插入数据?难道,memcached数据存储规则不是这样的,肯定有的东西我没了解到。首先会想到的问题:memcached是怎么插入数据的,插入的规则是什么?
要想真正的了解这个问题,需要对memcached作深入的了解。下面我简略的用几张图+简略的文字来说说memcached的原理。
memcached一般使用方式
memcached的分布式结构(通过客户端算法来实现的分布式,各服务端节点不通信)
数据存储机制(内在存储)
最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。主要解决了内存碎片问题。
请看引文
“he primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issues totally by using fixed-size memory chunks coming from a few predetermined size classes.”
解读:通过使用固定大小的内存块来减小内在碎片问题,(内存块的大小是预先定义好的--predetermined )。
Slab Allocation的主要术语
Page:分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
Chunk:用于缓存记录的内存空间。
Slab Class:特定大小的chunk的组。
Slab Allocation的原理: 将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合);slab allocator还有重复使用已分配的内存的目的(分配到的内存不会被释放)。
在Slab中是如何插入数据的呢?
即:数据会被插入比自己大的最小内存块(Slab预先分配的)中。显示,上图能发现,能存下100bytes是112bytes这个内存单元,这个内存单元剩下的空间是不能再被使用的,所以Slab机制也是有空间浪费的。可以通过增长因子来调优(默认值是1.25),具体应用后文会谈。
好了,现在我们对memcached 存储机制有一个理解了,根据现在掌握的理论,能解释一开始提出的问题么?
1. 在测试服务器上(环境与正式相同,使用的数据库都是相同的,唯一的不同是缓存服务器),程序正常执行,没有问题。
于是,写了一个测试程序来观测一下数据变化:
1.起服务,写了个批处理命令:
2. 上线后,在高峰期发现:参数类A无法写进缓存服务器。
3. 没招的情况下,重启memcached服务,又好了一阵,然后出现2错误。
为此,我做一个测试:Memcached(三):数据存储测试
得出:memcached的存储规则:(1.4..版本)
上述问题的原因:验证码占满了物理内存空间(5分钟内,1000多W条验证数据);当插入新的参数(数据较验证码大很多),并且这个参数的大小变化很大(赋值的不同),memcached试图去开辟一个新的空间,此是物理内存已经不可分配了,故就不能插入这个参数值了。
鉴于此,使用memcached应当注意最好存储一种类型大小的数据,这样基本上不会出事的;
如果真要存多种数据,也最好把握好参数的大小范围,设置好f值(增长因子值).