特点:
1、基于C/S架构,协议简单(基于文本协议);
2、基于libevent的事件处理;
(libevent是一套跨平台的事件处理接口的封装,能够兼容包括这些操作系统:
Windows/Linux/BSD/Solaris 等操作系统的的事件处理。poll、select(Windows)、epoll(Linux)、kqueue(BSD)、/dev/pool(Solaris) Memcached 使用libevent来进行网络并发连接的处理,能够保持在很大并发情况下,仍旧能够保持快速的响应能力。)
3、自主内存存储处理;
Slab 存储结构:
存储方式:
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 <size> <count>
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掉才能释放内存)
本文转自 位鹏飞 51CTO博客,原文链接:http://blog.51cto.com/weipengfei/1299855,如需转载请自行联系原作者