redis使用基础(九) ——Redis虚拟内存

redis使用基础(九)

——Redis虚拟内存

(转载请附上本文链接——linhxx)

一、概述

Redis的数据是保存在内存中,当物理内存不足,其会保存在虚拟内存(VM)中。Redis的vm类似操作系统的vm,其会把所有的键都存在内存中,而把部分很少被访问到的值放在硬盘中。

操作系统的vm是基于页的概念,linux每个页4KB,而redis很多对象远小于4KB。另外,redis将交换到磁盘的对象压缩,保存到磁盘的对象可以去除指针和对象元数据,这样可以减少很多的I/O操作。

redis的虚拟内存只能解决value太大的问题,因为其全部key都存在内存中,因此如果是key不足,则无法解决问题。

二、配置

修改相关配置文件,如下:

1、开启vm

vm-enabled yes

2、value保存在硬盘时的路径

vm-swap-file  /routetofile/redis.swap

3、最大内存上限,超出时开始使用vm

vm-max-memory  xx

4、每个页面的大小(字节)

vm-page-size xx

5、用于执行value对象换入换出的工作线程数量,通常设置成cpu内核数量

vm-max-threads  4

三、vm使用规则

redis根据以下算法将value存于vm中:

swappability = age * log(size_in_memory)

其中age是距离上一次被访问的时间,size_in_memory是value占用内存的大小。由于占用内存较大的value,取出来时消耗的I/O和CPU资源更多,因此在判断该取哪个value时,其权重更低,因此加上log计算。

四、vm开启限制

vm会按规则将部分value保存在硬盘,而redis的数据库备份通常采用rdb,其备份方式是主进程正常提供客户端操作,子进程去进行rdb备份。这可能会出现redis主进程在写vm的时候,正好子进程在备份。

为了避免此情况,redis做了限制,子进程在读vm时(无论是rdb还是aof),主进程不能进行value交换操作(因为通常读完一次value,其age变小,可能会从vm取出,而换新的value进去)。即此时两个进程都采用只读访问swap文件。

五、redis object 与 vm pointer

通常key和value都是redis的object,但是当value被移到vm时,其会变成vm pointer。其主要记录的是value在磁盘的信息,如记录对象在swap文件第几页开始、共使用几页等内容。

redis object和vm pointer 都有一个字段storage,用于判断value此时的位置,共有四种情况:redis_vm_memory(在内存里)、redis_vm_swapped(在磁盘里)、redis_vm_loading(在磁盘里,但目前正在有进程将其加载到内存)、redis_vm_swapping(在内存里,但目前正在有进程将其写入磁盘)

六、交换过程

1、将对象交换到swap文件

1)计算保存这个对象需要占用swap文件中的多少页。在代码中是通过调用函数rdbSavedObjectPages进行计算。

2)在swap文件中寻找一段连续空间保存这个对象。在代码中是通过调用函数vmFindContiguousPages进行计算。

该函数内部是从全部磁盘页中查找n块连续的空闲页,成功时返回redis_ok,并把first参数设置为连续页的开始地址。失败会返回redis_error。

3)把对象写入swap文件。在代码中是通过调用函数vmWriteObjectOnSwap进行计算。

该函数在写入文件之前,会先将swap文件锁住,防止其他进程也在进行此操作。接着把文件指针移动到要写入页的开始地址,并调用rdbSaveObject函数把对象写入swap文件。对象写入文件后,会释放内存,并把对象从redis object转成vm pointer。并且会将storage字段设置成redis_vm_swapped。

2、将对象从swap文件取出到内存

由于vm pointer记录了对象在文件的起始页和所占页数,因此只需要调用vmLoadObject函数,其最终会调用vmReadObjectFromSwap将对象写入内存

在将内存取出的过程中,也会锁住swap文件。

七、阻塞式VM

将上述配置文件中的vm-max-threads设置为0,即不开启多线程,则进行vm时会阻塞。将对象从内存交换到swap文件,发生在cron任务,每100毫秒执行一次。当redis对内存的使用超过设定的vm-max-memory,则会循环调用vmSwapOneObject函数,实现对象交换。

该操作步骤如下:

1)找一个较优的用来交换至swap分区的候选对象。

2)调用vmSwapObjectBlocking将对象所关联的value值交换到硬盘,此函数返回一个vmPointer指针,用于存储value在磁盘中的信息。

3)使用vmSwapObjectBlocking返回的vmPointer替换value对应的redisObject,并把storage设置为redis_vm_swapped,表示value已经交换到磁盘。

4)是否对象关联的value内存。

这个操作每次会释放一个object,因此会循环执行此函数,直到内存的使用下降到配置的vm-max-memory之下。

八、非阻塞式VM

阻塞式VM会导致读取swap文件时,锁住整个redis,这样其他客户端访问不在swap文件的value时,也会延迟。为了避免此问题,redis支持非阻塞式VM,是通过I/O线程实现。

具体来说,redis使用任务队列的方式,每当主线程需要在后台使用I/O线程完成任务,便push一个I/O任务到server.io_newjobs队列。当系统不存在活动I/O线程,便新建一个,会执行这些I/O任务。任务执行完成后,会将结果push到server.io_processed队列。该线程使用unix管道给主进程发送1字节信号,通知主线程有一个新任务已经完成。

——written by linhxx

更多最新文章,欢迎关注微信公众号“决胜机器学习”,或扫描右边二维码。

原文地址:https://www.cnblogs.com/linhxx/p/8412902.html

时间: 2024-10-07 14:50:21

redis使用基础(九) ——Redis虚拟内存的相关文章

Redis资料汇总(九) 虚拟内存

首先说明下redis的虚拟内存与os的虚拟内存不是一码事,但是思路和目的都是相同的.就是暂时把不经常访问的 数据从内存交换到磁盘中,从而腾出 宝贵的 内存空间用于其他需要访问的数据.尤其是对于redis这样的内存数据库,内存总是不够用的.除了可以将数据分割到多个redis server外.另外的能够提高数据库容量的办法就是使用vm把那些不经常访问的数据交换的磁盘上.如果我们的存储的数据总是有少部分数据被经常访问,大 部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃.当少量数据被经常访

Redis学习基础一

今天开始系统的学习redis基础知识,以往只是看redis的手册,貌似总是记不住.这次尝试手记笔记,使得印象更加深刻,从零开始学习.看是很慢,其实很快哟. 一.什么是Redis 至于什么是redis, 官网上这样给出:redis 是Salvatore Sanfilippo 这个人写的 Key-value 存储系统.Redis是一个开源的使用 C语言编写的,并且准守 BSD协议 属于Key-value 数据库.也被称为数据结构服务器,因为 value 可以是 (字符串,哈希,列表,集合,有序集合)

redis使用基础(十一) ——Redis特殊情况处理机制

redis使用基础(十一) --Redis特殊情况处理机制 (转载请附上本文链接--linhxx) 一.内存淘汰 当redis的内存不足时,需要采取内存淘汰的方法,共有两种方法.一是启用虚拟内存的方式,即将redis配置文件中的vm-enabled设置成yes:二是启用内存淘汰机制,即将redis配置文件中的maxmemory设置成一个大于0的整数. redis内存淘汰机制共有三种:随机淘汰(随机挑选键进行淘汰).LRU淘汰(查找键中最近最少访问的进行淘汰).TTL淘汰(查找键中离过期时间最近的

系统学习redis之一——基础概念

前言: redis集群搭建过很多次,也用过一些基础的命令,能解决一些常规的异常.但是因为平时对数据这块用得不多,一直没有很系统的学习过redis.这次将redis的知识好好学习了一下,记录为学习笔记<系统学习redis>系列. NoSQL介绍 非关系型数据库:NoSQL关系型数据库:MySQL.SQLserver.Oracle 关系型数据库在web2.0上对高并发,暴露出了一些性能问题 NoSQL 是以key-value形式存储,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,

Redis一点基础的东西

目录 1.基础底层数据结构 2.windows下环境搭建 3.java里连接redis数据库 4.关于认证 5.redis高级功能总结 1.基础底层数据结构 1.1.简单动态字符串SDS 定义: struct sdshdr{ int len; int free; char buf[]; } 优势: 为了重用部分C语言函数库功能,在buf里存储了空字符'\0',但是不同于C char[]的是: 取sds长度时,直接从len中获取,不是像C中遍历buf,直到遇到空字符结束. 在改变sds内容时,如果

也木有那么“高富帅”----Redis核心基础学习

由于工作慢慢从原来的少量用户的企业内部应用慢慢转化为了大量用户的企业内部应用或者直接转为了线上高并发应用,因而也渐渐的开始使用memcached.Redis等缓存服务器,为了便于自身的学习和记忆,特此成文.本文以window下的redis使用为例,实际中redis服务器会搭建在Linux服务器上. Redis核心特性简洁 借鉴知乎大牛的评价,Redis的快是因为:单进程单线程的避免了不必要的上下文切换和竞争条件:其绝大多数操作都是内存操作,虽然也支持虚拟内存:非阻塞IO.. 需要理解的几个知识点

基础拾遗------redis详解

基础拾遗 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗------接口详解 基础拾遗------泛型详解 前言 这篇文章和以往的基础拾遗有所不同,以前的介绍的都是c#基础,今天介绍的是redis.因为项目中一只在使用,我想现在大部分项目中都会用到nosql,缓存,今天就介绍一下redis..废话少说下面开始正题. 1.redis是什么? Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. 对的redi

redis的基础使用

首先需要加载php扩展配置 window需要先查看phpinfo配置文件 http://www.libaocai.com/3436.html redis windos安装教程 查看 是nts 还是ts http://windows.php.net/downloads/pecl/snaps/redis/2.2.5/ redis到这下载对应版本 这里也可以下载对应的dll http://pecl.php.net/package/redis/ php加载redis扩展 extension=php_re

Redis学习基础二

回顾:上一基础中已了解 ( 什么是redis .redis 的三大特点.安装,和数据配置) 接下来浅尝Redis的数据类型,时间煮雨...... 一.Redis数据类型 redis支持五中数据类型(string字符串.hash哈希.list列表.set集合.zset有序集合) (一)String 字符串 1.string 是redis 中最基本的类型,可以理解成与memcached一模一样的类型,一个key对应一个value 2.string 类型是二进制安全的,意思是redis 的string