memcached基础
memcached是高性能的分布式内存缓存服务器, 一般的使用的是通过其缓存数据库的查询结果,减少数据库的访问次数,以提高动态web应用的速度,提高可扩展性.
协议简单
memcached的服务器客户端通信并不使用复杂的XML等格式 而使用简单的基于文本行的协议
基于libevent的事件处理
libevent是个程序库,它将Linux的epoll,BSD类操作系统的kqueue等事件处理功能封装成统一的接口.即使对服务器的连接数增加,也能发挥O(1)的性能
内置内存存储方式
为了提高性能 memcached中保存的数据都存储在memcached内置的内存存储空间中.由于数据仅存在于内存中,因此重启memcached,重启操作系统会导致全部数据消失
memcached不互相通信的分布式
memcached尽管是分布式缓存服务器,但服务器端并没有分布式功能.各个memcached不会互相通信以共享信息.具体如何实现分布式,这完全取决于客户端的实现。
内部结构
memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存.在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的.但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢.Slab Allocator就是为解决该问题而诞生的.
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题.
Slab Allocation的原理相当简单.将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)
slab allocator还有重复使用已分配的内存的目的.也就是说,分配到的内存不会释放,而是重复利用.
Page
分配给Slab的内存空间,默认是1MB.分配给Slab之后根据slab的大小切分成chunk
Chunk
用于缓存记录的单位内存空间
Slab Class
特定大小的chunk的组
memcached根据收到的数据的大小,选择最适合数据大小的slab.memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk.然后将数据缓存于其中
Slab Allocator的缺点
Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题.这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存.例如,将100字节 的数据缓存到128字节的chunk中,剩余的28字节就浪费了.
分散算法
1.根据余数计算分散
根据服务器台数的余数进行分散 求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器.
缺点:
余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点.那就是当添加或移除服务器时,缓存重组的代价相当巨大.添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率.
2. Consistent Hashing 一致性哈希
首先求出memcached服务器(节点)的哈希值,并将其配置到0~232 的圆(continuum)上.然后用同样的方法求出存储数据的键的哈希值,并映射到圆上.然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上.如果超过232仍然找不到 服务器,就会保存到第一台memcached服务器上.
因此,Consistent Hashing最大限度地抑制了键的重新分布.而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想.使用一般的hash函数的话,服务器的映射地点的分布非常不均匀. 因此,使用虚拟节点的思想,为每个物理节点(服务器)在continuum上分配100~200个点.这样 就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布.
服务器台数(n)和增加的服务器台数(m) 计算增加服务器后的命中率计算公式如下: (1 n/(n+m)) * 100
应用
随着网站访问量的急剧增加,单纯为数据库添加 slave已无法满足需要,因此引入了memcached.