redis的VM机制

Redis处理的速度很快,因为它是基于内存的。在内存能够足够容纳数据的时候,所有的数据都存放在内存。这个时候不论是读取数据还是写入数据都是非常快的。但是如果数据量很大,大到内存已经无法全部容纳的时候,我想对存储有一定了解的人都在想,这个时候redis是怎么处理的呢?处理速度是否会直线下降?

幸亏,答案是否定的。Redis使用到了VM,在redis.conf设置vm-enabled yes 即开启VM功能。 通过VM功能可以实现冷热数据分离。使热数据仍在内存中,冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。在这里,需要特别提到的是,Redis并没有使用OS提供的Swap,而是自己实现。作者在自己的blog说明了原因:

1:OS是基于page(4K)来做的,它的粒度对于Redis来说太大。而redis的大多数对象都远小于4k,所以一个OS页面上可能有多个redis对象。另外redis的集合对象类型如list,set可能存在与多个OS页面上。最终可能造成只有10%的key被经常访问,但是所有OS页面都会被OS认为是活跃的,这样只有内存真正耗尽时OS才会交换页面。

2:相比于OS的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后对象会比内存中对象小10倍。这样redis的vm会比OS vm能少做很多io操作。

3:OS交换的时候,是会阻塞线程的,而Redis可以设置让工作线程来完成,主线程仍可以继续接收client的请求。

开启VM功能后,还有其他几个设置需要设置vm-swap-file:设置被交换出的值保存到磁盘的位置。vm-max-memory:设置当内存消耗达到上限时开始将value交换出来。vm-page-size:设置单个页面的大小,单位是字节。vm-pages:设置最多能交换保存多少个页到磁盘。可以算出可以交换出来的最大大小为vm-page-size * vm-pages。vm-max-threads:设置完成交换动作的工作线程数,设置为0表示不使用工作线程而使用主线程,这会以阻塞的方式来运行。建议设置成CPU核个数。

Redis为了保证查找的速度,只会将value交换出去,而在内存中保留所有的Key。所以它非常适合Key很小,Value很大的存储结构。如果Key很大,value很小,那么vm可能还是无法满足需求。redis规定同一个页面只能保存一个对象。但是一个对象可以保存在多个页面中。在redis使用的内存没超过vm-max-memory之前是不会交换任何value的。当超过最大内存限制后,redis会选择较老的对象。如果两个对象一样老会优先交换比较大的对象,将它从内存中移除,这样会更加节约内存。精确的公式swappability = age*log(size_in_memory)。

既然对于Redis来说,一个页面只会保存一个对象,也就是一个Value值,所以应该将vm-page-size设置成大多数value可以保存进去。如果设置太小,一个value对象就会占用几个页面,如果设置太大,就会造成页面空闲空间浪费。每个页面,Redis都会在内存中使用1比特(bit)长度来保存页面的空闲状态。如果设置的vm-pages非常大,那么光用来保存页面状态就会花费很大的内存。

VM的工作机制:分为两种

第一种:vm-max-threads = 0

换出

主线程定期检查使用的内存大小,如果发现内存超出最大上限,会直接以阻塞的方式,将选中的对象保存到换出文件中,并释放对象占用的内存,此过程会一直重复直到下面条件满足:
  1.内存使用降到最大限制以下,2. 设置的交换文件数量达到上限,3. 几乎全部的对象都被交换到磁盘了

换入

当有client请求的value之前已被换出时,主线程会以阻塞的方式从换出文件中加载对应的value对象,加载时此时会阻塞所有client,然后再处理client的请求。

第二种:vm-max-threads > 0

换出

当主线程检测到使用内存超过最大上限,会将选中的要交换的对象信息放到一个队列中交由工作线程后台处理,主线程会继续处理client请求。
   换入

如果有client请求value之前已被换出时,主线程先阻塞当个client,然后将加载对象的信息放到一个队列中,让工作线程去加载,此进主线程继续处理其他client请求。加载完毕后工作线程通知主线程。主线程再执行被阻塞的client的命令。这种方式只阻塞单个client。

注:
当前VM的坏处: slow restart 重启太慢 slow saving 保存数据太慢 slow replication 上面两条导致 replication 太慢 complex code 代码过于复杂
有可能被废弃哦,具体见:
https://yq.aliyun.com/ziliao/553403

参考链接:
https://www.cnblogs.com/xuegang/archive/2011/11/16/2250920.html

你可能感兴趣的:(redis)