memcached的内存分配没有用到c语言中自带的malloc函数,由于这个函数分配内存的时候效率很低,对于这种要求快速响应,对效率要求很是高的缓存软件来讲很是不合适。node
memcached用的是本身的一套内存分配方法,叫作slab allocation。算法
***64位的操做系统能分配 2GB 以上的内存。32位的操做系统中,每一个进程最多只能使用 2GB 内存。数据库
***若是想缓存更多的数据,建议仍是开辟更多的memcache进程(不一样端口)或者使用分布式memcache进行缓存,将数据缓存到不一样的物理机或者虚拟机上。数组
***memcached启动时指定的内存分配(如:-m 64)是memcached用于保存数据的量,不包括memcached自己占用的内存、以及为了保存数据而设置的管理空间。所以,memcached进程的实际内存分配量要比指定的容量要大。缓存
Memcache进程启动,在内存开辟了连续的区域。我们用上面的图形来举例,这段连续的区域就好像上面的slab1+slab2+slab3+……+slab(n).分配区域相同的构成了slab(分片组)。Slab下面可不直接就是存储区域片(就是图中的chunks)了。而是page,若是一个新的缓存数据要被存放,memcached首先选择一个合适的slab,而后查看该slab是否还有空闲的chunk,若是有则直接存放进去;若是没有则要进行申请。服务器
slab申请内存时以page为单位,因此在放入第一个数据,不管大小为多少,都会有1M大小的page被分配给该slab。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,在从这个chunk数组中选择一个用于存储数据。在Page中才是一个个小存储单元——chunks,一个page默认1mb,那么能够放多少个88字节单位的chunks呢?1024*1024/88约等于11915个。若是放入记录是一个100字节的数据,那么在88字节的chunks和112字节的chunks中如何调配呢。答案固然是紧着大的用,不可能将请求过来的数据再作个分解、分离存储、合并读取吧。这样也就带来了一个小问题,仍是有空间浪费掉了。112-100=12字节,这12字节就浪费了。负载均衡
Memcache借助了操做系统的libevent工具作高效的读写。libevent是个程序库,它将Linux的epoll、BSD类操做系统的kqueue等事件处理功能封装成统一的接口。即便对服务器的链接数增长,也能发挥高性能。memcached使用这个libevent库,所以能在Linux、BSD、Solaris等操做系统上发挥其高性能。Memcache号称能够接受任意数量的链接请求。事实真的是这样吗?分布式
**一个memcahced进程会预先将本身划分为若干个slab,slab得数量是有限的,跟进程配置的内存无关,跟-f(增加因子),-I(page大小),-n(初始chunk大小)有关。memcached
**slab的数量最大是200(当指定-f 1.0001)时,增加因子越大,slab越少,-f 不能小于1。函数
**能够经过-I指定page的大小,单位是byte,page默认是1M,最小须要1024byte, page值设置的越大slab越多。
**-n(最小分配空间):即初始chunk的大小,默认是48,此时初始chunk的大小是96,(注意并非2倍的关系,当设置为50时,第一个chunk的大小是104),-n越大slab越少。
**一个slab能够申请多个page,当前slab下没有数据时不会分配page。
推荐:对slab,page,chunk解释的较详细:http://tank.blogs.tkiicpp.com/2010/12/14/memcache%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5/
存储过程分析
假设咱们如今往memcache中存储一个缓存记录,首先在使用memcache客户端程序的时候要制定一个初始化的服务机器路由表,好比PHP的客户端程序
$mc = new Memcache();
$mc->addserver('192.168.1.110',11211);
$mc->addserver('192.168.1.120',11211);
$mc->addserver('192.168.1.130',11211);
那么在作存储的时候memcache客户端程序会hash出一个码,以后再根据路由表去将请求转发给memcache服务端,也就是说memcache的客户端程序至关于作了一个相似负载均衡的功能。
而memcache在server上面的进程仅仅负责监听服务和接受请求、存储数据的做用。分发不归他管。因此这么看的话,散列到每台memcache服务机器,让每台机器分布存储得均匀是客户端代码实现的一个难点。这个时侯Hash散列算法就显得格外重要了吧。
读取过程分析
理解了memcache的存储就不难理解memcache的读取缓存的过程了。在读取的时候也是根据key算出一个hash,以后在算出指定的路由物理机位置,再将请求分发到服务机上。
memcache分布式读写的存储方式有利有弊。若是node2宕机了,那么node2的缓存数据就没了,那么还得先从数据库load出来数据,从新根据路由表(此时只有node1和node3),从新请求到一个缓存物理机上,在写到重定向的缓存机器中。灾难恢复已经实现得较为完备。弊端就是维护这么一个高可用缓存,成本有点儿大了。为了存储更多的数据,这样作是否利大于弊,仍是得看具体的应用场景再定。