`
pengpeng
  • 浏览: 82511 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
阅读更多


memcached特点

协议简单
基于libevent的事件处理
内置内存管理
memcached不互相通信的分布式

交互过程
memcached 的客户端使用TCP链接 与 服务器通讯。(UDP接口也同样有效,参考后文的 ;UDP协议 )一个运行中的memcached服务器监视一些(可设置)端口。客户端连接这些端口,发送命令到服务器,读取回应,最后关闭连接。鼓励客户端缓存这些连接,而不是每次需要 存取数据时都重新打开连接。这是因为memcached 被特意设计成及时开启很多连接也能够高效的工作(数百个,上千个如果需要的话)。缓存这些连接,可以消除建立连接所带来的开销(/*/相对而言,在服务器 端建立一个新连接的准备工作所带来的开销,可以忽略不计。)。

用于客户端从服务器端存取数据时。同样服务器会以字节流的方式传回自由数据。/*/服务器不用关心 自由数据的字节顺序。自由数据的特征没有任何限制;但是通过前文提到的文本行,这项数据的接受者(服务器或客户端),便能够精确地获知所发送的数据库的长度。

约定
文本行固定以\r\n(回车符紧跟一个换行符)结束。 自由数据也是同样会以;\r\n结束,但是 \r(回车符)、\n(换行符),以及任何其他8位字符,均可出现在数据中。因此,当客户端从服务器取回数据时,必须使用数据区块的长度来确定数据区块的 结束位置,而不要依据数据区块末尾的\r\n


键值(key)
存储命令(set、add、repalce)指示服务器储存一些由键值标识的数据。客户端发送一行命令,后面跟着数据区块;然后,客户端等待接收服务器回传的命令行,指示成功与否。
取回命令(只有一项:'get')指示服务器返回与所给键值相符合的数据(一个请求中右一个或多个键值)。客户端发送一行命令,包括所有请求的键值;服务器每找到一项内容,都会发送回客户端一行关于这项内容的信息,紧跟着是对应的数据区块;直到服务器以一行;END;回应命令结束。
其他的命令都不能携带自由数据。在这些命令中,客户端发送一行命令,然后等待(由命令所决定)一行回应,或最终以一行;END;结束的多行命令。

时间参数
一些客户端发送给服务器的命令会包含一些时限(针对内容或客户端请求的操作)。这时,时限的具体内容既可以是Unix时间戳(从1970年1月1日开始的秒钟数),或当前时间开始的秒钟数。对后者而言,不能超过 60*60*24*30(30天);如果超出,服务器将会理解为Unix时间戳,而不是从当前时间起的秒偏移。

内置内存管理
memcached中保存的数据都存储在memcached内置的内存存储空间中。重启memcached、重启操作系统会导致全部数据消失。 另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。memcache采用Slab Allocation的内存管理方式,原理:将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合)。同样大小的slab可以有很多页。slab allocator还有重复使用已分配的内存的目的。 也就是说,分配到的内存不会释放,而是重复利用。这种方式在有效的防止内存碎片产生的同时会浪费一些空间,但对于大规模应用来说,这点浪费不算问题。另外可以通过调整slab中chunk的大小来减少空间的浪费,这个调整在生产环境中非常重要。

Slab Allocation的主要术语

Slab Class 特定大小的chunk的组。

Page 分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。slab可以认为是一个结构,同一个结构下,可以有很多份空间,这每一份就是一个Page
Chunk 用于缓存记录的内存空间。

缺点
Slab Allocator解决了内存碎片问题,但新的机制也给memcached带来了新的问题。
由于分配的是特定长度的内存,因此无法有效利用分配的内存。 例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了 ,而每个Slab 1M的限制加少最少分为2个chunk的结构,使memcached不适合缓存大于500K的数据。
使用Growth Factor进行调优
通过启动参数控制 : Growth Factor = 2
memcached -f 2 -vv -l 127.0.0.1 -p 1111
slab class 1: chunk size 128 perslab 8192
slab class 2: chunk size 256 perslab 4096
slab class 3: chunk size 512 perslab 2048
memcached -f 1.25 -vv -l 127.0.0.1 -p 1111
slab class 1: chunk size 80 perslab 13107
slab class 2: chunk size 100 perslab 10485

这个字节对其是否是和cpu cache(cache line)的字节对齐?

查看slabs的使用状况

http://code.sixapart.com/svn/memcached/trunk/server/scripts/memcached-tool
使用方法也极其简单:
$ memcached-tool 主机名:端口 选项
查看slabs使用状况时无需指定选项,因此用下面的命令即可:

获得的信息如下所示:
# Item_Size Max_age 1MB_pages Count Full?
3 128 B 6 s 1 100 no
33 103.4 kB 1308 s 1 9 yes
40 492.9 kB 1373 s 51 102 yes
各列的含义为:

含义
#
slab class编号
Item_Size
Chunk大小
Max_age
LRU内最旧的记录的生存时间
1MB_pages
分配给Slab的页数
Count
Slab内的记录数
Full?
Slab内是否含有空闲chunk
删除机制
memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况, 此时就要使用名为 Least Recently Used(LRU)机制来分配空间。 顾名思义,这是删除"最近最少使用"的记录的机制。 因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。

分布式方式
memcached尽管是分布式缓存服务器,但服务器端并没有分布式功能。 各个memcached不会互相通信以共享信息,它和分布式没任何关系。如何分步完全取决于客户端的实现。

余数分散
根据服务器台数的余数进行分散, 求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器。

余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。 那就是当添加或移除服务器时,缓存重组的代价相当巨大。 添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器, 从而影响缓存的命中率。

Consistent Hashing的简单说明

从上图的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化 而影响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的 第一台服务器上的键会受到影响。

memcached以后会支持外部存储

memcached支持外部存储的难点是,网络和事件处理相关的代码(核心服务器)与 内存存储的代码紧密关联。这种现象也称为tightly coupled(紧密耦合)。 必须将内存存储的代码从核心服务器中独立出来,才能灵活地支持外部引擎。 因此,基于我们设计的API,memcached被重构成下面的样子:

memcachedb

http://memcachedb.org/
遵循memcached的协议(完全兼容memcached接口,使用memcached的程序可以直接切换),加bdb持久化。
Replication Model
单master
多点可读
事物保证

memcached适合的场景
由于每个slab最大是1M,如果存超过1M的内容,直接出错。而实际上更严格,通过-f参数,最大size的slab中chunk也会有2个,也就是说 最大的chunk size也只有不到1/2M(有一些空间可能对齐或其他的预留不能完全使用)。如果数据很大带来的另一个严重的问题是内存浪费。简单来算一下。数据块比较 大的时候,只能使用到大的slab,当步长为1.25时,最大的3个slab依次是:492k,394k,315k,跨度越来越大,浪费的比例越来越大。 所以对于对memcached的使用,应该事先清楚数据的结构以及大小,配置合适的slab步长。数据体尽量不要太大。memcache用来cache文件,是不行的,除非在上层把文件切分。
另一个问题是LRU,LRU只会发生在同一个slab中,这就是说,如果对于相同的业务,数据大小差异比较大时,对cache的使用效果会和期望的有所不同。
鼓励客户端缓存这些连接,而不是每次需要 存取数据时都重新打开连接。这是因为memcached 被特意设计成及时开启很多连接也能够高效的工作(数百个,上千个如果需要的话)。缓存这些连接,可以消除建立连接所带来的开销(/*/相对而言,在服务器 端建立一个新连接的准备工作所带来的开销,可以忽略不计。)。
将memcached引入产品,或是直接使用默认值进行部署时, 最好是重新计算一下数据的预期平均长度,调整growth factor, 以获得最恰当的设置。
问题:每个slab的大小是固定在哪里的,但是否已经占用了内存?
slab建立的时候并没有真正的分配内存,page建立的时候才分配内存。每个slab管理1M内存,其下可以建立很多各page,page创建的时候才真正的分配了内存。这和slab allocator的方式好像略有不同。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics