对于redis 这样的内存数据库, 内存总是不够用的。 除了可以将数据分割到多个 redis 服务器以外。 另外的能够提高数据库容量的办法就是使用虚拟内存技术把那些不经常访问的数据交换到磁盘上

如果我们存储的数据总是有少部分数据被经常访问,大部分数据很少被访问, 对于网站来说确实总是只有少量用户经常活跃。 当少量数据被经常访问时, 使用虚拟内存不但能提高单台 redis 数据库服务器的容量,而且也不会对性能造成太多影响。

redis 没有使用操作系统提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内

存机制。
主要的理由有以下两点:
1. 操作系统的虚拟内存是以 4k/页为最小单位进行交换的。而 redis 的大多数对象都远小
于 4k,所以一个操作系统页上可能有多个 redis 对象。另外 redis 的集合对象类型如
list,set 可能存在于多个操作系统页上。最终可能造成只有 10%的 key 被经常访问,但
是所有操作系统页都会被操作系统认为是活跃的,这样只有内存真正耗尽时操作系统才
会进行页的交换。
2. 相比操作系统的交换方式。 redis 可以将被交换到磁盘的对象进行压缩,保存到磁盘的对
象可以去除指针和对象元数据信息。一般压缩后的对象会比内存中的对象小 10 倍。这
样 redis 的虚拟内存会比操作系统的虚拟内存少做很多 IO 操作

Redis 虚拟内存相关配置

vm-enabled yes    #开启虚拟内存功能

vm-swap-file /tmp/redis.swap    #交换出来 value 保存的文件路径/tmp/redis.swap

vm-max-memory 268435456     #redis 使用的最大内存上限(256MB) ,超过上限后redis 开始交换 value 到磁盘 swap 文件中。建议设置为系统空闲内存的 60%-80%

vm-page-size 32       #每个 redis 页的大小 32 个字节

vm-pages 134217728       #最多在文件中使用多少个页,交换文件的大小 =(vm-page-size * vm-pages)4GB

vm-max-threads 8     #用于执行 value 对象换入换出的工作线程数量。0表示不使用工作线程(详情后面介绍)

redis 的虚拟内存在设计上为了保证 key 的查询速度,只会将 value 交换到 swap 文件
中。如果是由于太多 key 很小的 value 造成的内存问题,那么 redis 的虚拟内存并不能解
决问题。和操作系统一样 redis 也是按页来交换对象的。redis 规定同一个页只能保存一个
对象。 但是一个对象可以保存在多个页中。 在 redis 使用的内存没超过 vm-max-memory 之前
是不会交换任何 value 的。 当超过最大内存限制后, redis 会选择把较老的对象交换到 swap
文件中去。如果两个对象一样老会优先交换比较大的对象,精确的交换计算公 式
swappability = age*log(size_in_memory)。 对于 vm-page-size 的设置应该根据自己应用
将页的大小设置为可以容纳大多数对象的尺寸。 太大了会浪费磁盘空间, 太小了会造成交换

文件出现过多碎片。对于交换文件中的每个页,redis 会在内存中用一个 1bit 值来对应记
录页的空闲状态。所以像上面配置中页数量(vm-pages 134217728 )会占用 16MB 内存用来记
录页的空闲状态。vm-max-threads 表示用做交换任务的工作线程数量。如果大于 0 推荐设
为服务器的 cpu 的核心数。如果是 0 则交换过程在主线程进行

redis 虚拟内存工作方式简介

1. 当 vm-max-threads 设为 0 时(阻塞方式)

换出
主线程定期检查发现内存超出最大上限后,会直接以阻塞的方式,将选中的对象保存到 swap
文件中,并释放对象占用的内存空间,此过程会一直重复直到下面条件满足
①.内存使用降到最大限制以下
②.swap 文件满了。
③.几乎全部的对象都被交换到磁盘了

换入
当有客户端请求已经被换出的 value 时,主线程会以阻塞的方式从 swap 文件中加载对应的
value 对象,加载时此时会阻塞所有客户端。然后处理该客户端的请求

2. 当 vm-max-threads 大于 0 时(工作线程方式)

换出
当主线程检测到使用内存超过最大上限, 会将选中要交换的对象信息放到一个队列中交给工
作线程后台处理,主线程会继续处理客户端请求。
换入
如果有客户端请求的 key 已经被换出了, 主线程会先阻塞发出命令的客户端, 然后将加载对
象的信息放到一个队列中,让工作线程去加载。加载完毕后工作线程通知主线程。主线程再
执行客户端的命令。这种方式只阻塞请求的 value 是已经被换出 key 的客户端。
总的来说阻塞方式的性能会好一些, 因为不需要线程同步、 创建线程和恢复被阻塞的客
户端等开销。但是也相应的牺牲了响应性。工作线程方式主线程不会阻塞在磁盘 IO 上,所
以响应性更好。 如果我们的应用不太经常发生换入换出, 而且也不太在意有点延迟的话推荐
使用阻塞方式

redis虚拟内存的更多相关文章

  1. redis虚拟内存---官方文档

    http://redis.io/topics/internals-vm Virtual Memory technical specification This document details the ...

  2. Redis教程(十一):虚拟内存介绍:

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/138.html 一.简介: 和大多NoSQL数据库一样,Redis同样遵循 ...

  3. Redis学习手册(虚拟内存)

    一.简介: 和大多NoSQL数据库一样,Redis同样遵循了Key/Value数据存储模型.在有些情况下,Redis会将Keys/Values保存在内存中以提高数据查询和数据修改的效率,然而这样的做法 ...

  4. Redis系列文章导读

    1. Redis简介 1.1 Redis VS Memcached 2. Redis安装教程 3. Redis数据类型 4. Redis常用命令 4.1 key 4.2 string 4.3 hash ...

  5. redis入门教程

    21) Redis 简介Redis 是一个开源的使用 ANSI C 语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库.2) 数据类型2.1. Redis 的 KeyRedi ...

  6. Redis 常见面试题

    使用Redis有哪些好处? 速度快 基于内存,避免了磁盘I/O的瓶颈. 单进程单线程,减少了线程上下文切换的开销 利用队列技术将并行访问变为串行访问,消除了传统数据库并发访问控制锁的开销. Redis ...

  7. Redis 小结

    一.redis简介 redis是一款基于C语言编写的,开源的非关系型数据库,由于其卓越的数据处理机制(按照规则,将常用的部分数据放置缓存,其余数据序列化到硬盘),大家也通常将其当做缓存服务器来使用. ...

  8. redis 从0 到 1 键值相关命令 服务器相关命令

    keys * 获取所有的key   忽略其数据类型 数据为空   返回(empty list or set) keys a* .*b 获取以a开头 或者 以b结尾的key 返回(empty list ...

  9. 77%的Linux运维都不懂的内核问题

    前言 之前在实习时,听了 OOM 的分享之后,就对 Linux 内核内存管理充满兴趣,但是这块知识非常庞大,没有一定积累,不敢写下,担心误人子弟,所以经过一个一段时间的积累,对内核内存有一定了解之后, ...

随机推荐

  1. Python中加入中文注释

    最近开发学习Pyton,当加入中文注释时,运行程序报错: File SyntaxError: Non-ASCII character , but no encoding declared; see h ...

  2. JAVA覆写Request过滤XSS跨站脚本攻击

    注:本文非本人原著. demo的地址:链接:http://pan.baidu.com/s/1miEmHMo 密码:k5ca 如何过滤Xss跨站脚本攻击,我想,Xss跨站脚本攻击令人为之头疼.为什么呢. ...

  3. day12 函数的嵌套调用 闭包函数,函数对象

    函数嵌套: 函数嵌套: 嵌套指的是,一个物体包含另一个物体,函数嵌套就是一个函数包含另一个函数 按照函数的两个阶段 嵌套调用 指的是在函数的执行过程中调用了另一个函数,其好处可以简化外层大函数的代码, ...

  4. Es6对象的扩展和Class类的基础知识笔记

    /*---------------------对象的扩展---------------------*/ //属性简写 ,属性名为变量名, 属性值为变量的值 export default functio ...

  5. 通过$broadcast或$emit在子级和父级controller之间进行值传递

    通过$broadcast或$emit在controller之间进行值传递,不过这些controller必须是子级或者父级关系, $emit只能向父级parent controller传递事件event ...

  6. 爬虫框架之Scrapy

    一.介绍 二.安装 三.命令行工具 四.项目结构以及爬虫应用简介 五.Spiders 六.Selectors 七.Items 八.Item Pipelin 九. Dowloader Middeware ...

  7. LeetCode(118):杨辉三角

    Easy! 题目描述: 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例: 输入: 5 输出: [ [1], [1,1] ...

  8. 2019-3-9,Servlet转跳链接详解

    //以下代码,可以传递request和response对象及其属性和变量至指定页面 request.getRequestDispatcher("showAttribut.jsp") ...

  9. 泛微云桥e-Bridge安装手册

    有时候不看官方文档进行配置,可能会出现奇奇怪怪的问题,SO转载一下官方文档,顺带学习. 想超长体验此软件,请搜索本博客内容,有破解方法,仅用来学习使用,顺带进行二次开发,请勿使用在商业用途,谢谢. 泛 ...

  10. NHibernate:no persister for 异常

    几种原因: 1.配置文件后缀名写错 mapping file 必须是.hbm.xml结尾 2.Web.config配置里面引用实体 <session-factory> .......... ...