Memcached是高性能的分布式内存缓存服务器。它的主要目的不是基于本地缓存的,而主要用在分布式系统中。Memcached中保存的数据都存储在Memcached内置的内存存储空间中。因为数据仅存在于内存中,所以重启Memcached、重启操做系统会致使所有数据消失。Memcached是记录级的缓存,以前调研报告里提到过与MySQL、Server等页级缓存会缓存无效数据的,记录级的缓存则使内存利用率更高。算法
1、Memcached的内存管理方式数组
memcached默认状况下采用了Slab Allocator的机制分配、管理内存。在该机制出现之前,内存的分配是经过对全部记录简单地进行malloc和free来进行的。可是,这种方式会致使内存碎片,加剧操做系统内存管理器的负担,Slab Allocator就是为解决该问题而诞生的。缓存
SlabAllocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以彻底解决内存碎片问题。下面我会介绍内存分配过程。服务器
Memcached将内存分红多个slab,每一个slab是一次申请内存的最小单位(大小为1M不过好像能够设置),slab内部又分为若干个chunk。chunk的大小分为不少种,以80字节为初始大小(称为id-0的slab),第二类大小为第一类的f倍(f为参数可调,称这类为id-1的slab),随id递增每一类比上一类的chunk大小大f倍。因此一个chunk最大只可能为1M。每一个chunk里包含了一个item结构体(key和value),用来存放缓存数据。chunk大小相同的已分配空间的slab组成一个链表,全部的slab链表都保存在一个slabclass的数组上(至关于二维链表),每一种slab在初始化时默认都会建立一个。分布式
2、Memcached缓存记录的原理memcached
memcached接收到一条记录时,首先会知道item的大小,而后就会在slabclass数组上去找能包含这个item的最小的chunk的slab链表(因为memcached的各链表之间chunk大小的倍数关系,能够快速定位到链表的起始位置),找到空闲的chunk缓存这条记录。当一个slab的chunk都用完,则新申请新的slab用来存item,申请的slab的大小是倍数变化的(和std::vector同样),链表大小由1变2,由2变四、八、16……若是空间已满,不能申请更多slab,则按照LRU原则,将空间分配给新的记录。函数
3、Memcached的内存浪费性能
memcached的内存主要表现有如下三处:spa
一、一个slab分配1M空间,而slab中全部chunks大小加起来可能到不了1M;操作系统
二、每类slab在初始化时默认都会建立一个,可是若是这类slab从未被使用过,则这1M就浪费了;
三、一个item的大小老是不大于chunk大小的,当小于时则发生内存冗余。
第一类能够经过参数调优尽可能减小这种内存冗余,第二类应该也能够减小,第三类看起来就不太少避免。
4、Memcached的分布式算法
Memcached的服务器端主要是用来记录缓存和读取,而分布式算法即选择哪台服务器来寻找数据/写入内存则由客户端程序库实现。方法是用Consistent Hash。
ConsistentHashing以下所示:首先求出memcached服务器(节点)的哈希值(memcached用CRC计算哈希值),并将其配置到0-232的圆上。而后用一样的方法求出存储数据的键的哈希值,并映射到圆上。而后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。
从上图的状态中添加一台memcached服务器。传统的取模算法会使大量的键不能哈希到以前缓存的服务器上,但Consistent Hashing中,只有在增长服务器的地点逆时针方向的第一台服务器上的键会受到影响(以下图)。
所以,Consistent Hashing最大限度地抑制了键的从新分布。有的ConsistentHashing的实现方法还采用了虚拟节点的思想。使用通常的hash函数的话,服务器的映射地点的分布很是不均匀。所以,使用虚拟节点的思想,为每一个物理节点(服务器)在continuum上分配100~200个点。这样就能抑制分布不均匀,最大限度地减少服务器增减时的缓存从新分布。
(转载本文请注明出处: http://blog.csdn.net/jiang1st2010/article/details/8121361)