天天看点

Memcached小结

 特点:

 1、基于C/S架构,协议简单(基于文本协议);

 2、基于libevent的事件处理;

 (libevent是一套跨平台的事件处理接口的封装,能够兼容包括这些操作系统:

Windows/Linux/BSD/Solaris 等操作系统的的事件处理。poll、select(Windows)、epoll(Linux)、kqueue(BSD)、/dev/pool(Solaris) Memcached 使用libevent来进行网络并发连接的处理,能够保持在很大并发情况下,仍旧能够保持快速的响应能力。)

 3、自主内存存储处理;

<a href="http://blog.51cto.com/attachment/201309/215347760.png"></a>

   Slab 存储结构:

<a href="http://blog.51cto.com/attachment/201309/215553238.png"></a>

 存储方式:

   Slab是一次申请内存的最小单位,每个slab都是1MB

   Slab Allocation;避免大量重复的初始化和清理—减轻内存管理器负担

   避免频繁malloc/free –避免造成过多的碎片

 过期方式:Lazy Expiration + LRU

   不检测item对象是否超时,get时检查item对象是否应该删除;

   删除item对象时,不释放内存,作删除标记,指针方式slot回收插槽,下次分配的时候直接使用;

 Item是保存在chunk中的实际数据;

 控制内存的浪费:

   Slab尾部剩余空间规划:

   slab=chunk*n整数倍;使用合适的factor:

 启动方式:    

   -d 以守护程序(daemon)方式运行

   -u root 指定用户,如果当前为 root ,需要使用此参数指定用户

   -P /tmp/a.pid保存PID到指定文件

 内存设置:

   -m 1024 数据内存数量,不包含memcached本身占用,单位为 MB

   -M 内存不够时禁止LRU,报错

   -n 48初始chunk=key+suffix+value+32结构体,默认48字节

   -f 1.25 增长因子,默认1.25

   -L启用大内存页,可以降低内存浪费,改进性能

  连接设置:

   -l 127.0.0.1 监听的 IP 地址,本机可以不设置此参数

   -p 11211 TCP端口,默认为11211,可以不设置

   -U 11211 UDP端口,默认为11211,0为关闭

  并发设置:

   -c 1024最大并发连接数,默认1024,最好是200

   -t 4线程数,默认4。由于memcached采用NIO,所以更多线程没有太多作用

   -R 20每个event连接最大并发数,默认20

   -C禁用CAS命令(可以禁止版本计数,减少开销)

  举例:/usr/local/bin/memcached -d -u nobody -m 1024 -p 11210 -l 10.11.12.70 -P /opt/memcached/pid/m11210.pid

 Memcached命令列表;

   存储命令:set/add/replace/append/prepend/cas

   读取命令:get/gets

   删除命令:delete

   计数命令:incr/decr

   统计命令:stats/settings/items/sizes/slabs/

   工具命令:memcached-tool

   set无论如何都进行存储

   add只有数据不存在时进行添加

   repalce只有数据存在时进行替换

   cas按版本号更改 cas 即 check and set,只有版本号相匹配时才进行存储,否则返回exists (设计意图: 解决多个客户端并发修改同一条记录的问题,防止使用经过改变了的value/key 对)  

 stats统计项:

   分析CPU占用是否过高:

   rusage_system:该进程累计的系统时间 /s

   rusage_user:该进程累计的用户时间 /s

 分析连接数是否太多:

   curr_connections:当前连接数

   total_connections:memcached 自运行以来接受的连接总数

 分析命中率是否太低:

   Cmd_get 查询请求总数

   Get_hits 查询成功获取数据的总次数

   Get_missess 查询成功未取到数据的总次数

 分析字节数量:

   Bytes    memcached当前存储内容所占总字节数

   Bytes read  memcached从网络读取到的总字节数

   Bytes written memcached 向网络发送的总字节数

 分析对象数LRU频率:

   Curr_items  memcached当前存储的item数量

   Total_items  memcached 启动以来存储过的内容总数

   Evictions   LRU释放对象数,用来释放内存

 Stats settings 查看设置:

   Maxbytes  最大字节数限制

   Maxconns  允许最大连接数

   Tcport

   Udpport    

   Evictions on/off 是否禁用LRU

   Growth_factor 增长因子 (每个slab class 增长的倍数,默认为1.25)

   Chunk size  key+valus+flags大小

   Num_threads 线程数,可通过-t设置,默认为4(一般选定为CPU核数)

 Stats sizes 对象数量统计 Look:会锁定服务,暂停处理请求:

   显示的格式: stat &lt;size&gt; &lt;count&gt;

 Stats slabs 区块统计:

   Chunk_size : chunk 大小,byte

   Chunks_per_page : 每个page的chunk 数量

   Total_pages : pages 数量

   Total_chunks = chunk数量* page数量

 其他命令; flush_all 清除所有数据

   Echo flush_all | nc localhost 11210  

 UDP协议:

   TCP 连接客户端过多时选用;

   允许少量的操作失败??

 可以使用replaced来实现Memcached主从复制!

 部分不足:

   Can’t dump 无法备份,重启无法恢复

   没有持久化,重启全部丢失

   单点故障failover

   崩溃没法查找原因

   任何机器都可以telnet,需要放在防火墙后

   内存问题

   LRU是slab局部,没有全局

   有空间浪费

   没有合理的日志

   集群增加机器成本

FAQ:

   1、memcached能接受的key的最大长度是250个字符

250是memcached服务器端内部的限制。如果使用的Memcached客户端支持"key的前缀"或类似特性,那么key(前缀+原始key)的最大长度是可以超过250个字符的。推荐使用较短的key,这样可以节省内存和带宽。

       2、单个item的大小被限制在1M byte之内

       每个slab只负责一定范围内(chunk数据大小决定)的数据存储。每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。

Memcached的内存存储引擎,使用slabs来管理内存。内存被分成大小不等的slabs chunks(先分成大小相等的slabs,然后每个slab被分成大小相等chunks,不同slab的chunk大小是不相等的)。chunk的大小依次从一个最小数开始,按某个因子增长,直到达到最大的可能值。如果最小值为400B,最大值是1MB,因子是1.20,各个slab的chunk的大小依次是:slab1 - 400B;slab2 - 480B;slab3 - 576B ...slab中chunk越大,它和前面的slab之间的间隙就越大。因此,最大值越大,内存利用率越低。Memcached必须为每个slab预先分配内存,因此如果设置了较小的因子和较大的最大值,会需要为Memcached提供更多的内存。

不要尝试向memcached中存取很大的数据,例如把巨大的网页放到mencached中。因为将大数据load和unpack到内存中需要花费很长的时间,从而导致系统的性能反而不好。如果确实需要存储大于1MB的数据,可以修改slabs.c:POWER_BLOCK的值,然后重新编译memcached;或者使用低效的malloc/free。另外,可以使用数据库、MogileFS等方案代替Memcached系统。

      3、memcached的内存分配器是如何工作的?为什么不适用malloc/free!?为何要使用slabs?

默认会使用内部的slab分配器,而且确实应该使用内建的slab分配器。最早的时候,memcached只使用malloc/free来管理内存。然而,这种方式不能与OS的内存管理以前很好地工作。反复地malloc/free造成了内存碎片,OS最终花费大量的时间去查找连续的内存块来满足malloc的请求,而不是运行memcached进程。slab分配器就是为了解决这个问题而生的。内存被分配并划分成chunks,一直被重复使用。因为内存被划分成大小不等的slabs,如果item的大小与被选择存放它的slab不是很合适的话,就会浪费一些内存。

      4、memcache已经分配的内存不会再主动清理

      5、memcache分配给某个slab的内存页不能再分配给其他slab。

      6、flush_all不能重置memcache分配内存页的格局,只是给所有的item置为过期。(LRU不是全局的,而是针对Slab而言的,所以可能会造成新数据被清楚掉;只有delete掉才能释放内存)

<b></b>

<b>本文转自 位鹏飞 51CTO博客,原文链接:http://blog.51cto.com/weipengfei/1299855,如需转载请自行联系原作者</b>

继续阅读