内存分配机制:首先要说明的是Memcached支持最大的存储对象为1M。它的内存分配比较特殊,但是这样的分配方式其实也是对于性能考虑的,简单的分配机制可以更容易回收再分配,节省对于CPU的使用。这里用一个酒窖比喻来说明这种内存分配机制,首先在Memcached起来的时候可以通过参数设置使用的总共的Memory,当你第一次往Memcached存储数据时, Memcached会去申请1MB的内存, 把该块内存称为一个slab, 也称为一个page, 如果可以存储这个数据的最佳的chunk大小为128B,那么Memcached会把刚申请的slab以128B为单位进行分割成8192块. 当这页slab的所有chunk都被用完时,并且继续有数据需要存储在128B的chunk里面时,如果已经申请的内存小于最大可申请内存10MB 时,Memcached继续去申请1M内存,继续以128B为单位进行分割再进行存储;如果已经无法继续申请内存,那么Memcached会先根据LRU 算法把队列里面最久没有被使用到的chunk进行释放后,再将该chunk用于存储. 这个就是建造一个酒窖,然后在有酒进入的时候,首先申请(通常是1M)的空间,用来建酒架,酒架根据这个酒瓶的大小分割酒架为多个小格子安放酒瓶,将同样大小范围内的酒瓶都放置在一类酒架上面。例如20cm半径的酒瓶放置在可以容纳20-25cm的酒架A上,30cm半径的酒瓶就放置在容纳25-30cm的酒架B上。回收机制也很简单,首先新酒入库,看看酒架是否有可以回收的地方,如果有直接使用,如果没有申请新的地方,如果申请不到,采用配置的过期策略。这个特点来看,如果要放的内容大小十分离散,同时大小比例相差梯度很明显,那么可能对于使用空间来说不好,可能在酒架A上就放了一瓶酒,但占用掉了一个酒架的位置。
为了避免使用Memcached时出现异常, 使用Memcached的项目需要注意:
1. 不能往Memcached存储一个大于1MB的数据.
2. 往Memcached存储的所有数据,如果数据的大小分布于各种chunk大小区间,从64B到1MB都有,可能会造成内存的极大浪费以及Memcached的异常.
优化可以从以下几个方面进行:
1. 命中率.
对于缓存服务而言,命中率是至关重要的.命中率的提升可以通过多种方案实现.其一,提高服务获取的内存总量.这无疑是增加命中的最直接的办法,将缓存数据完全放入数据池中.只要连接不失效,就一定命中.其二,提高空间利用率,这实际上也是另一种方式的增加内存总量.具体实现在下一个方面给出.其三,对于一些很特别的memcache应用,可以采用多个memcache服务进行侦听,分开处理,针对服务提供的频繁度划分服务内存,相当于在应用一级别上再来一次LRU.其四,对于整体命中率,可以采取有效的冗余策略,减少分布式服务时某个server发生服务抖动的情况.如,14台机器实现分布式memcache,划分两组服务,其中一组13台做一个分布式的memcache,一组1台做整个的memcache备份.对于update操作,需要进行两边,get操作只需要一遍,一旦访问失效,则访问备份服务器.这样,对于备份服务器需要内存比较大,而且只适应于读操作大于写操作的应用中.这可以认为是RAID3,当然,也可以采用RAID1完全镜像.
2. 空间利用率.
对于使用memcache做定长数据缓存服务而言,是可以在空间利用率上进行优化.甚至最简单的办法可以不用更改memcache的源码遍可以完成由-f和-n参数的配合可以做到定长优化,不过极可能需要浪费掉预分配的199M内存空间.当然前提是memcache的版本是1.2,同时如果使用的是1.2.0和1.2.1的话,需要更改掉一个BUG,那就是getopt时将opt串中最后一个”s”改成”n”,希望memcache能在以后的版本发现这个BUG.例如,如果key是一个定长id(如一个8位的流水号00000001),value是一个定长的串(如16位的任意字符串),对应于一个chunk_size可以这么计算:chunk_size = sizeof(item) + nkey + nsuffix + nbytes = 32 + 8 + (flag长度 + (16 - 2)的长度 + 2) + 16 = 40 + 5 + 16 = 61,那么可以通过-f 1.000001 -n 61来启动memcache.这种情况下,会浪费掉memcache预先分配的200M空间中的199M.从第2个预分配等级到第200个预分配等级将不会用到.然而,存在解决办法,那就是在编译memcache是加入编译参数-DDONT_PREALLOC_SLABS,或者在源代码中加入#define DONT_PREALLOC_SLABS即可,只是会去除memcache的预分配内存机制.
4. 安全性能.
memcache还存在一个比较显著的问题,那就是其安全性能.只要了解memcache监听的端口,对于能够使用分布式memcache进行数据通信的网络环境的机器,都可以通过memcache协议于memcache服务器进行通信,获取或种植数据.不能保证种植进内存里的数据不会被别有心意的人再利用.也不能保证服务器的内存不被漫天遍地的垃圾数据所堆积,造成命中极低.
memcache的设计理念在一个轻字,如果对每次Client的通讯需要校验身份,那么恐怕memcache也就达不到其想要的效果了.存在解决办法缓解这个问题,一般而言,需要使用memcache服务的机器,可以在Server维持一张红色列表.这张表上的机器便可以获取服务.很显然,memcache并非任意Client都能访问,只有信任的机器访问,那么为什么不将这些信任的机器放在一个/etc/mem_passwd下呢.
原文地址:http://blog.csdn.net/stuartjing/article/details/8263895