31
8月

关于Memcached的一些事

主要启动参数

-p:设置TCP监听端口。如果-l选项包含端口,则不使用本端口;如果没有-p选项有-U选项,那么tcp端口与UDP端口相同。

-U:设置UDP端口(0不使用UDP)。如果-l选项包含端口,则不适用本端口;如果没有-U选项有-p选项,那么UDP端口与tcp端口相同。

-l:指定监听地址,默认INADDR_ANY或监听地址和端口,并且可以指定多个端口。例如:-l 0.0.0.0:10086 -l 0.0.0.0:10087。如果-l参数中有监听地址,那么将不适用-p和-U设置端口。

-s:unix本地域socket文件路径。

-a:指定-s选项中socket权限,默认0700。

-d:以守护进程方式运行。

-r:设置core文件为RLIM_INFINITY

-u:指定用户,当使用root用户运行memcached时,启动后将进程转换到该用户下。

-m:最大数据内存数量,item使用内存,非程序本身使用,单位为MB。

-M:指定该选项,内存不足,不足以分配slab时报错。否则强制itemLRU替换。

-c:打开最大文件描述符数目。setrlimit调节。

-k:锁住程序内存页mlockall(MCL_CURRENT | MCL_FUTURE)。ulimit -l 参数查看系统限制。

-P:保存PID到执行文件中。-d模式启动使用。启动时检查文件中的进程并杀掉进程。

-f:chunk增长因子,默认1.25。

-n:指定最小chunk的key+suffix+value大小。Item (no cas) 48,Item(cas) 56。当指定-C选项时,最小chunk为-n指定大小+48;当没有-C选项时,最小chunk为-n指定大小+56。

-L:大内存模式,启动时分配-m参数指定大小内存,可以检查内存碎片,增加内存利用率。需要操作系统支持(getpagesizes,memcntl)。

-t:启动处理网络请求线程数。默认是4。

-R:每个线程最大处理请求事件数目。

-C:不适用CAS命令,item没有版本号。

-b:tcp连接请求的最大数量(backlog队列最大数量)。

-B:协议ascii,binary,auto(默认)。auto根据请求内容自动判断,binary0x80开头

-I:指定item大小:default: 1mb, min: 1k, max: 128m
-D:设置key前缀和key值的分隔符,默认“:”,例如 “-D ‘#’”,则”get name#wang“命令时,会统计前缀name的命中次数等。

-o:4个子参数选项。maxconns_fast,hashpower=13(大于12,小于64),slab_reassign,slab_automove=0(默认),1,2。

1)         maxconns_fast:当连接数超过最大连接数(-c),立即返回错误并关闭连接。

2)         hashpower:设置hashpower_init。

3)         slab_reassign:启动SLAB重分配线程,slab_reassign=true。

4)         当slab_automove=2时,当第一次发生LRU后(没有指定-M选项,并且内存不足时。),从slabclass1开始向后查找一个有2个slab page以上的slab class并将第一页强制分配给发生LRU的slabclass。第二次发生LRU后,会从上一次选取的class之后进行查找合适的class进行page转移。

5)         当slab_automove=1时,有slab_maintenance_thread线程自己选取src page,dest page进行转移。10秒检查一次。

启动举例:memcached -d -n 96 -l 0.0.0.0:10086 -l 0.0.0.0:10087 -I 64M -t 4 -C -m 1024 -o slab_reassign,slab_automove=1 -D ‘#’ -vvv

memcached机制

 

•守护进程机制
–UNIX daemon
•Socket事件处理机制
–non-blocked:非阻塞
–libevent:异步事件处理
–epoll/kqueue
•内存管理机制
–slab:内存分配机制
–LRU:对象清除机制
–Hash机制:快速检索item
•多线程处理机制:pthread(POSIX)线程模式
–编译时开启:./configure –enable-threads
–目前还比较粗糙,锁机制locking不够完善
–负载过重时,可以开启(-t线程数为CPU核数)
•SLAB内存处理机制
–提前分配大内存slab 1MB(因为page默认为1MB),再进行小对象填充chunk
–避免大量重复的初始化和清理à减轻内存管理器负担
–避免频繁malloc/freeà系统碎片
•懒惰检测机制
–不检测item对象是否超时
–get时检查item对象是否应该删除
•懒惰删除机制
–删除item对象时,不释放内存,作删除标记,指针放入slot回收插槽,下次分配的时候直接使用

Page为内存分配的最小单位

Memcached的内存分配以page为单位,默认情况下一个page是1M,可以通过-I参数在启动时指定。如果需要申请内存 时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在重启前不会被回收或者重新分配(page ressign已经从1.2.8版移除了)

 

Slabs(slab class)划分数据空间

Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs(slab class),每个slab只负责一定范围内(chunk数据大小决定)的数据存储。每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:slab 3只存储大小介于137 到 224 bytes的数据。如果一个数据大小为230byte将被分配到slab 4中。memcached默认情况下下一个slab存储数据的最大值为前一个的1.25倍,这个可以通过修 改-f参数来修改增长比例。

Chunk才是存放缓存数据的单位

Chunk是一系列固定的内存空间,这个大小就是管理它的slab的最大存放大小。例如:slab 1的所有chunk都是104byte,而slab 4的所有chunk都是280byte。chunk是memcached实际存放缓存数据的地方,因为chunk的大小固定为slab能够存放的最大值, 所以所有分配给当前slab的数据都可以被chunk存下。如果时间的数据大小小于chunk的大小,空余的空间将会被闲置,这个是为了防止内存碎片而设 计的。例如下图,chunk size是224byte,而存储的数据只有200byte,剩下的24byte将被闲置。

 

slab内存分配

Memcached在启动时通过-m指定最大使用内存,但是这个不会一启动就占用,是随着需要逐步分配给各slab的。
如果一个新的缓存数据要被存放,memcached首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如 果没有则要进行申请。slab申请内存时以page为单位,所以在放入第一个数据,无论大小为多少,都会有1M大小的page被分配给该slab。申请到 page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,在从这个chunk数组中选择一个用于存储 数据。如下图,slab 1和slab 2都分配了一个page,并按各自的大小切分成chunk数组。

Memcached内存分配策略

memcached的内存分配策略就是:按slab需求分配page,各slab按需使用chunk存储。
这里有几个特点要注意,

  1. Memcached分配出去的page不会被回收或者重新分配
  2. Memcached申请的内存不会被释放
  3. slab空闲的chunk不会借给任何其他slab使用
  4. 新版本中Page可以调配给其它的Slab,shell> memcached -o slab_reassign,slab_automove

Memcached的LRU机制

为了规避内存碎片问题,Memcached采用了名为SlabAllocator的内存分配机制。内存以Page为单位来分配,每个Page分给一个特定长度的Slab来使用,每个Slab包含若干个特定长度的Chunk。实际保存数据时,会根据数据的大小选择一个最贴切的Slab,并把数据保存在对应的Chunk中。如果某个Slab没有剩余的Chunk了,系统便会给这个Slab分配一个新的Page以供使用,如果没有Page可用,系统就会触发LRU机制,通过删除冷数据来为新数据腾出空间,这里有一点需要注意的是:LRU不是全局的,而是针对Slab而言的。

 

slab内存结构图:二维数组链表

slab内存分配实例

Item内存分配(chunk中的实际数据)

 

新建Item分配内存过程

•快速定位slab classid
–计算key+value+suffix+32结构体,如90byte
–如果>1MB,无法存储丢弃
–取最小冗余的slab class
•如:有48,96,120,存90会选择96
•按顺序寻找可用chunk
–slot:检查slab回收空间slot里是否有剩余chunk
•delete:delete时标记到slot
•exptime:get时检查的过期对象标记到slot
–end_page_ptr:检查page中是否有剩余chunk
–memory:内存还有剩余则开辟新的slab
–LRU:Slab内部扫描Item双向链表50次

减少内存浪费

•调优方法:
–f参数:factor增长因子
–n参数:chunk初始值

 

•slab尾部剩余空间
•如classid=40中,两个chunk占用了1009384byte,就有1048576-1009384=39192byte被浪费
•解决办法:规划slab=chunk*n整数倍
• slab中chunk利用率低:申请的slab只存放了一个Item
•解决办法:规划slab=chunk
•chunk存储Item浪费
•如I tem是100,存到128字节chunk,就有28字节浪费
•解决办法:规划chunk=Item
使用合适的factor,减少浪费
•-f参数:默认为1.25,曾经为2
•值越小,slab中chunk size差距越小,内存浪费越小
•1.25适合缓存几百字节的对象
根据数据分布调整factor
•非均匀分布,即数据长度集中在几个区域内
–如保存用户Session
•更极端的状态是等长数据
–如定长键值,定长数据
–多见于访问、在线统计或执行锁
•计算Item长度
–key键长+suffix+value值长+结构大小(32字节)

 因为优秀,所以不足

•Can’t dump
–无法备份,重启无法恢复
•Can’t iterate over keys
–无法查询
•Not persistent
–没有持久化,重启全部丢失
•Not redundant
–单点故障failover
•No Sessions
–崩溃没法查找原因
•No security
–任何机器都可以telnet,需要放在防火墙后
•内存问题
–LRU是slab局部,没有全局
–有空间浪费
•日志问题
–没有合理的日志
•集群问题
–集群增加机器成本高

 продвижение брендов в интернете юридических услугдам деньги в долг в уфепарк нгоронгоропроизводители посуды в россииgoogle ads keywordрекламное агентство ярославльпроверка сайта по запросамкупить биметаллический радиатор отопленияправильная установка радиатора отопленияМототерра отзывы сотрудников

引用地址:http://www.hikin.net/?p=1246

  留言暂时关闭