和大多数NoSQL一样,Redis也是使用的KV的数据存储模型,为了提高读写效率,Redis也是将KV保存在内存中,但是这样做会带来一些问题。
如果 内存足够大,那么把所有的数据都加载到内存中固然是最好的选择,那么查询操作都直接操作内存,自然是很快。但是实际情况中却更多的是只有部分数据才能加载到内存中,那么这个时候就提出来一个虚拟内存的概念。
Redis中的虚拟内存和Linux中的虚拟内存不是一回事,但是其思想是一致的,就是把暂时不常用的数据从内存交换到磁盘中,从而可以把宝贵的内存腾出来用于其他需要访问的数据,尤其是像Redis这样的内存数据库,内存的数量无意会成为一个瓶颈。虽然我们可以把数据分割到多个服务器上,但是虚拟内存依然是一个相当有效的解决办法。
使用虚拟内存还有另外一个原因,那就是在我们的数据库中,被访问的数据总是占全部数据的一小部分,而大部分的数据都是很少被访问的,就网站用户来说,活跃用户总是占据少部分。
但是Redis没有使用Linux提供的虚拟内存机制,它是实现了自己的虚拟内存机制,主要原因有两点:
(1)Linux虚拟内存的粒度过大,在Linux中使用4KB的页面,这对于Redis来说太大了,二Redis中的绝大多数对象都远远小于这个数值。
(2)Redis可以在把数据交换到磁盘上的时候进行适当的操作,比如压缩,通常保存到磁盘上的对象可以去除指针和对象元数据信息,一般压缩后的对象可以比内存中的对象小10倍。这样可以节省很多IO操作。
当然,并不是所有场景都适合虚拟内存。这里需要注意的就是Redis中的Key是不会被交换的,如果每个key所关联的value都很小,那么这种场景就不太适合于使用虚拟内存了。如果key比较小,但是对应的value比较大,那么这种场景是最适合使用虚拟内存的场景。
下面是一些常见的配置项:
(1)vm-enabled yes 表示在服务器启动时开启虚拟内存的功能。
(2)vm-max-memory 它是Redis使用的最大内存上限,它以字节为单位
(3)vm-pages 表示最多使用多少个页面
(4)vm-page-size 表示每个页面的大小,以字节为单位
(5)vm-max-threads 它是用于执行value对象换入换出的工作线程数量
接下来就是Redis的几个规定:
(1)Redis为了保证key的查找速度,只会将value交换到swap文件中。
(2)Redis在进行数据交换的时候,也是使用页面来交换的,而且Redis规定一个页面只能保存一个对象,但是一个对象可以保存到多个页面中。
(3)Redis使用的内存没有超过vm-max_memory之前是不会交换任何的value的,当超过最大内存的限制之后,Redis会选择过期的对象,如果两个对象过期时间一样,那么它会优先交换比较大的对象。
(4)如果vm-page-size设置的太小,会造成交换文件出现碎片,太大又会浪费空间。
(5)对于交换文件的每个页面,Redis都会在内存中对应一个bit值来记录页面的空闲状态。
(6)而vm-max-threads用来表示用作交换任务的线程数,如果大于0的话,则推荐为CPU的核的数量,如果是0则交换过程在主线程中执行
(7)对Redis而言,如果操作交换文件是以同步的方式进行的,那么当某一客户端正在访问交换文件的数据时,如果其他客户端也试图去访问交换文件中的数据,那么后面的这个客户端的请求会被挂起,直到之前的操作结束为止。如果在比较忙的时候读取较大的时,这种阻塞带来的后果会更严重。
原文地址:http://blog.csdn.net/xinguimeng/article/details/43884893