在redis中并不是所有的数据都存储在内存中的,这是和memcached相比的一个最大的区别,当物理内存用完的时候,redis可以将一些很久没有用到的value交换到磁盘,redis只会缓存所有的key信息,如果redis发现内存的使用量超过了某一个阀值,将触发swap的操作,redis根据swappablity=age*log(size_in_memory)”计算出哪些key对应的value需要Swap到磁盘,然后将这些key对应的value持久化到磁盘中,同时在内存中清除,这种特性使得redis可以保持超过其机器本身内存大小的数据,当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的,同时由于redis将内存中的swap到磁盘的时候,提供服务的主线程和进行swap操作的子线程会共享这部分的内存,所以如果更新需要swap的数据,热第三将阻塞这个操作,直到子线程完成swap操作后才可以进行修改,当从redis中读取数据的时候,如果读取的key对应的value不在内存中,那么redis需要从swap文件中加载相应数据,然后再返回给请求方,这里就存在一个I/O线程池的问题,在默认情况下,redis会出现阻塞,即完成所有的swap文件后加载后才会相应,这种侧罗在客户端的数量少,进行批量操作的时候比较合适,但是如果将redis应用在一个大型的网站应用的程序中,这种显然无法满足大并发的情况。所以redis运行我们设置I/O线程池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间
对于像redis和memchached这种基于内存的数据库系统来说,内存的管理效率高低是影响系统性能的关键因素,传统C语言汇总的malloc/free函数时常用的分配和释放内存的方法,但是这种方法存在很大的缺陷,首先对于开发人员开说不匹配的malloc和free容易造成内存泄漏,其次频繁的调用会造成大量的内存碎片无法回收重新利用,降低内存的利用率,最后作为系统调用,其系统开销远远大于一般函数调用,所以为了提高内存的管理效率,高校的内存管理方案都不会直接使用malloc/free调用,redis和memcached均使用了自身设计的内存管理机制,但是实现方法存在很大的差异,
Memcached的特征:
Memechaced作为高速运行的分布式缓存服务器,具有以下特点:
协议简单
基于libevent的事件处理
基于内存存储方式
Memcached互不相护通信的分布式
协议:
Memecacehd的服务端通信并不适用复杂的xml格式,而是适用简单基于文本行的协议
内置内存存储方式
为了提高性能,memecached中保存的数据都保存在memecacehd内置的内存空间中的,由于数据存在于内存中,因此重启memecached,重启操作系统,会导致全部数据消失,另外,内容容量达到指定值之后,就基于LRU(least recently used)算法自动删除不适用的缓存,memecached本身为缓存设计的服务器,因此并没有过多的考虑数据的永久性问题,
Memecached尽管是“分布式”缓存服务器,但是服务器端并没有分布式功能,各个memecached不会互相通信共享信息,那么,怎样进行分布式呢,这完全取决于客户端实现
安装memcached
Memecached依赖libevent类库
Sudo yum install libevent libevent-devel
下载memecached
Wget http://www.danga.com/memcached/dist/memcached1.2.5.
tar.gz
tar zxfmemcached-1.2.5.tar.gz
cd memecached-1.2.5
./configure
Make
Sudo make install
Memecached启动
/usr/local/bin/memcachedp
11211m
64mvv
slab class
$/usr/local/bin/memcached p
11211m
64mvv
slabclass 1: chunk size 88 perslab 11915
slabclass 2: chunk size 112 perslab 9362
slabclass 3: chunk size 144 perslab 7281
中间省略
slabclass 38: chunk size 391224 perslab 2
slabclass 39: chunk size 489032 perslab 2
<23server listening
<24send buffer was 110592, now 268435456
<24server listening (udp)
<24server listening (udp)
<24server listening (udp)
<24 serverlistening (udp)
这里显示了调试信息。这样就在前台启动了memcached,监听TCP端口11211最大内存使用量为
64M。调试信息的内容大部分是关于存储的信息
p
使用的TCP端口。默认为11211
m
最大内存大小。默认为64M
vv
用very vrebose模式启动,调试信息和错误输出到控制台
d
作为daemon在后台启动
上面四个是常用的启动选项,其他还有很多,通过
$ /
作为daemon后台启动时,只需
$/usr/local/bin/memcached p
11211m
64m d
理解memcached的内存存储
Slab allocation机制:整理内存以便重复使用
最近的memcached默认情况下采用了名为slab allocation机制分配管理内存,在该机制出现之前,内存的分配是通过对所有记录简单的进行malloc和free来进行的,但是这种会导致内存碎片,家中操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memecached本身还慢,slab Allocator 就是为解决这问题而诞生的
将分配的内存分割成各种尺寸的块,并把尺寸相同的块分组成组(chunk集合)Slab Class
其中chunk就是用来存储key_value数据的最小单位,每个slab class的大小,可以在memcached启动的时候通过指定Growth Factor来控制定图中Growth Factor的取值为1.25,如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推。
Page
分配给slab的内存空间,默认是1M
Chunk
用于缓存记录的内存空间
Slab class
特定大小的chunk的组
Memcaced如何针对客户端发送过来的数据选择slab并缓存到chunk中
Memecacehd根据收到的数据大小,选择最合适数据大小的slab,memecached中保存着slab内空闲
Chunk的列表,根据该列表选择chunk,当一条数据过期或者丢弃时,从以上过程我们可以看出memechaced的内存管理效率高,而且不会造成内存碎片
Slab allocator的缺点
Slab allocator解决了当初的内存碎片问题,但是新的机制也给memecached带来了新的问题,这个问题就是,由于分配的是特定长度的内存,因此无法有效地利用分配的内存,例如将100字节的数据缓存到128字节的chunk,剩余的28字节就浪费了,
使用GrowthFactor进行调优
Memechaed在启动的时指定Frowth Factor因子(通过-f 选项)就可以在某种程度上控制slab之间的差异,默认值为1.25,但是,在在该选项出现之前,这个因子固定为2,成为 powers of 2”策略
Memecached –f 2 –vv
slabclass 1: chunk size 128 perslab 8192
slabclass 2: chunk size 256 perslab 4096
slabclass 3: chunk size 512 perslab 2048
slabclass 4: chunk size 1024 perslab 1024
slabclass 5: chunk size 2048 perslab 512
slabclass 6: chunk size 4096 perslab 256
slabclass 7: chunk size 8192 perslab 128
slabclass 8: chunk size 16384 perslab 64
slabclass 9: chunk size 32768 perslab 32
slabclass 10: chunk size 65536 perslab 16
slabclass 11: chunk size 131072 perslab 8
slabclass 12: chunk size 262144 perslab 4
slabclass 13: chunk size 524288 perslab 2
Memecached的删除机制
Memecached是缓存,所以数据不会永久保存在服务器上,这是向系统中引入memecached的前提
Memechaced在数据删除方面有效利用资源
数据不会真正从memecached中消失
Memecacehd不会释放已分配的内存,记录超时后,客户端就无法再看见该记录,其内存空间即可重复使用
Memecached内部不会监视记录是否过期,而是在get时查看记录的事件戳,检查记录时候过期,这种技术成为lazy(惰性)expiration。因此,memecached不会在过期监视上耗cpu时间
从缓存中有效删除数据的原理
Memechached会优先使用已经超时的记录的空间,但即使如此,也会发现新记录时空间不足的问题,这时就要使用LRU机制来分配空间,因此当memecached的内存空间不足时无法从slab class获取到新的空间时,就是从最近未被使用的记录中搜索,并将其空间分配给新的记录,从缓存的实用角度看,十分的理想