【IT168 专稿】首先说明下redis的虚拟内存与操作系统的虚拟内存不是一码事,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用的。
除了可以将数据分割到多个redis server外。另外的能够提高数据库容量的办法就是使用虚拟内存把那些不经常访问的数据交换的磁盘上。如果我们的存储的数据总是有少部分数据被经常访问,大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用虚拟内存不但能提高单台redis server数据库的容量,而且也不会对性能造成太多影响。
redis没有使用操作系统提供的虚拟内存机制而是自己在实现了自己的虚拟内存机制,主要的理由有两点:
1、操作系统的虚拟内存是已4k页面为最小单位进行交换的。而redis的大多数对象都远小于4k,所以一个操作系统页面上可能有多个redis对象。另外redis的集合对象类型如list,set可能存在与多个操作系统页面上。最终可能造成只有10%key被经常访问,但是所有操作系统页面都会被操作系统认为是活跃的,这样只有内存真正耗尽时操作系统才会交换页面。
2、相比于操作系统的交换方式,redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息,一般压缩后的对象会比内存中的对象小10倍,这样redis的虚拟内存会比操作系统虚拟内存能少做很多io操作。
下面是vm相关配置:
vm-swap-file /tmp/redis.swap #交换出来的value保存的文件路径
vm-max-memory 1000000 #redis使用的最大内存上限
vm-page-size 32 #每个页面的大小32个字节
vm-pages 134217728 #最多使用多少页面
vm-max-threads 4 #用于执行value对象换入换出的工作线程数量
redis的虚拟内存在设计上为了保证key的查找速度,只会将value交换到swap文件中。所以如果是内存问题是由于太多value很小的key造成的,那么虚拟内存并不能解决,和操作系统一样redis也是按页面来交换对象的。redis规定同一个页面只能保存一个对象。但是一个对象可以保存在多个页面中。在redis使用的内存没超过vm-max-memory之前是不会交换任何value的。当超过最大内存限制后,redis会选择较过期的对象。如果两个对象一样过期会优先交换比较大的对象,精确的公式swappability = age*log(size_in_memory)。对于vm-page-size的设置应该根据自己的应用将页面的大小设置为可以容纳大多数对象的大小,太大了会浪费磁盘空间,太小了会造成交换文件出现碎片。对于交换文件中的每个页面,redis会在内存中对应一个1bit值来记录页面的空闲状态。所以像上面配置中页面数量(vm-pages 134217728 )会占用16M内存用来记录页面空闲状态。vm-max-threads表示用做交换任务的线程数量。如果大于0推荐设为服务器的cpu内核的数量,如果是0则交换过程在主线程进行。