辛星浅谈Redis中的虚拟内存

和大多数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而言,如果操作交换文件是以同步的方式进行的,那么当某一客户端正在访问交换文件的数据时,如果其他客户端也试图去访问交换文件中的数据,那么后面的这个客户端的请求会被挂起,直到之前的操作结束为止。如果在比较忙的时候读取较大的时,这种阻塞带来的后果会更严重。

时间: 2024-12-16 11:57:51

辛星浅谈Redis中的虚拟内存的相关文章

辛星浅谈Redis中的事务

Redis也提供了对事务的支持,在Redis中,我们常用的命令就是multi.exec.discard.watch这四个命令.其中multi命令用于开始一个事务,该语句之后的所有命令都会被视为事务之内的操作,而exec是提交一个事务,discard是回滚一个事务. 下面是对一些命令的具体介绍: multi----用于标记事务的开始,其后执行的命令都被存放于命令队列,直到执行exec时,这些命令才会被原子的执行.它的返回值总是OK. exec----执行在一个事务内命令队列中的所有命令,同时将当前

辛星浅谈mysql中的元数据

首先解释一下什么是元数据,所谓元数据,就是表示数据的数据,这些数据五花八门,总之,只要不是我们存储到数据库里的数据,大多都可以理解为元数据.那么我们如何来获取这些元数据呢? 总的来说,有三种思路,第一种,各种show,第二种,各种select,第三种,是mysql的命令行下的命令,不是sql语句. 我们首先看第一种,这里我列举一下大家比较熟悉的show语句的用法,其实咱们经常用show来查看信息,比如: show databases; show tales; show create table

辛星浅谈mysql中的数据碎片以及引擎为MyISAM下的操作

对于mysql中的数据碎片,其实和我们删除数据是息息相关的,删除数据的时候必然会在数据文件中造成不连续的空白空间,对于少量的数据的删除,并不会产生多少的空白空间.如果在一段时间内的大量的删除操作,会使得这种留空的空间变得比存储列表内容所使用的空间更大.可能有人会说,我们向数据库中插入数据的时候,会不会在这些空白空间中插入数据呢?答案是会的.但是,它会造成一个后果,那就是数据的存储位置不连续,以及物理存储顺序与理论上的存储顺序不相同,这就比较麻烦了. 按照数据碎片的大小来分,可以分为单行数据碎片和

辛星浅谈Linux中的环境变量

全局变量和本地环境变量: bash  shell使用一种称为环境变量的特性来存储关于shell会话和工作环境的信息,这也是环境变量的名字的由来.该特性还允许我们把数据存储在内存中,以便于在shell中运行的程序或者脚本中访问它们.bash  shell中共有两种类型的环境变量:全局变量和本地变量. 全局环境变量在shell会话和该shell产生的任何子进程中都可见.而本地变量则只在创建它们的shell中可见.在产生需要父进程信息的子进程的应用程序中,这便体现了全局变量的重要作用.系统环境变量使用

辛星浅谈PHP的混乱的编码风格

我们都知道,各种编程语言都有自己的风格,即使是像C和C++那样一脉相承的语言(C++本意完全兼容C的语法),编程风格上还是有些差别,比如很典型的就是C++风格的单行注释和C风格的多行注释. 而虽然Java在很大程度上借鉴了C的语法,但是不可否认,Java的经典的大括号是左大括号是在类名或者函数名等同一行的,而C++风格的则是大括号另起一行,可能有些Java程序员和C++程序员这两种风格都用,但是如果大家多看看大师的编码风格,会发现其实大括号另起一行是典型的C++的风格,大括号不另起一行是典型的J

辛星浅谈大型网站构架优化思路之一简化

其实谈到大型网站,它和小型的站点几乎是两个概念,其概念的差别就像航空母舰和独木舟的区别那样,中国早在黄帝炎帝时代就可以制作独木舟了,但是生产航空母舰呢?因为航空母舰太大了,规模的提升带来了很多问题,那么如何去分析并且解决这些问题呢? 我感觉大型网站更应该去简化,不应该为了复杂而复杂,我感觉一套优秀的简化方案是优化网站的最有效的途径,没有之一,什么意思呢?如果让我们的货车跑得更快,那么少拉一些不必要的货物是最有效的方式,也应该是我们真正去优化一个网站的第一步. 那么该如何去简化呢?我们不妨从可以简

辛星浅谈大型网站架构思路之二分解

第一节中我们讨论了简化,如果简化完毕,或者无法简化,那么就要考虑分解它了,那么如何去分呢?通常来说,可以从横向和纵向去分,也可以从软件和硬件去分,这个和我们构架的设计方面有关. 横向分解之我见: ①所谓横向分解,就是分离出的各个部分不存在明显的层次关系,彼此之间独立性较强,当然完全的独立是不现实的. ②第一点思路就是根据功能去分,比如网站分为bbs来交流问题,blog来展示博文信息,news来展示新闻等等,那么可以考虑根据二级域名来做相应的部署,比如bbs放到一台服务器上,blog放到一台服务器

浅谈数据库系统中的cache(转)

http://www.cnblogs.com/benshan/archive/2013/05/26/3099719.html 浅谈数据库系统中的cache(转) Cache和Buffer是两个不同的概念,简单的说,Cache是加速"读",而buffer是缓冲"写",前者解决读的问题,保存从磁盘上读出 的数据,后者是解决写的问题,保存即将要写入到磁盘上的数据.在很多情况下,这两个名词并没有严格区分,常常把读写混合类型称为buffer cache,本文后续的论述中,统一

【转】浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初