过期键删除策略

对于过期键值的删除有三种常见的做法

  1. 定时删除。为每一个过期的键创建一个定时器,过期立刻删除。

    优点:及时删除过期键值,释放内存空间

    缺点:如果过期键值较多时,在删除过期键值上占用的CPU较多,而在内存充足的情况下,过期键值其实是不必急着删除的,应该优先把CPU用在处理客户端请求上
  2. 惰性删除。当访问键的时候判断这个键是否已过期,过期就删除。

    优点:对CPU占用最少,不会在删除其他过期的键上花费时间

    缺点:不能及时删除键,释放内存。如果一个过期的键永远没有被访问,那么这个键就不会被删除,无用的垃圾数据会堆积在内存中,造成内存泄露
  3. 定期删除。每隔一段时间遍历一遍所有设置了过期时间的键,删除已过期键。

    优点:相对定时删除,占用的CPU时间更少,相对惰性删除,在执行频率设置合理的情况下也能及时删除过期键,释放内存

    缺点:频率很难设置,设置的过于频繁会退化成定时删除,设置的执行间隔太长,会导致过期键不能及时删除

Redis采用了惰性删除和定期删除,可以在合理使用CPU时间和避免浪费内存空间上取得平衡。另外在定期删除策略上也做了优化,每次执行定期删除会有最大执行时间限制,如果达到时间上限还没执行完会记录当前位置并停止处理,下次从纪录点继续执行

持久化

Redis是内存数据库,当Redis进程退出后,保存在内存中的数据就会丢失。为了解决这个问题,Redis提供了RDB跟AOF两种方式,将数据库状态进行持久化到磁盘中

RDB

RDB文件保存了Redis在某个时间点上的数据库状态,类似于快照,可以使用RDB文件将Redis数据恢复。Redis提供了两个命令生成RDB文件,分别是SAVE跟BGSAVE,区别是SAVE是由服务器进程直接执行,会阻塞服务器,BGSAVE是由子线程执行保存,不会阻塞服务器。

Redis默认设置了多个保存条件,900秒内对数据库修改1次、300秒内对数据库修改10次、60秒内对数据库修改10000次,服务器中有一个周期性执行的serverCron默认每隔100毫秒执行一次,在serverCron执行时检查只要其中任何一个条件得到满足就会执行BGSAVE命令自动保存。

AOF

除了RDB外,Redis还提供了AOF持久化功能,区别于RDB是通过直接保存数据库键值,AOF是通过保存服务器执行的写命令来记录数据库状态。当服务器的AOF功能打开的时候,每当服务器进行写操作,都会有对应的写命令记录在AOF的缓冲区中,缓冲区中的数据会根据配置持久化到文件中,目前AOF提供三种持久化的选项,分别是always(将缓冲区所有内容写入并同步到文件)、erverysec(每秒将缓冲区内容写入到文件)、no(由操作系统控制何时同步)



使用AOF还原数据库状态流程

AOF重写

前面讲到,AOF文件是具体执行的写命令记录,随着执行命令的次数越来越多,AOF文件内容会越来越大,为了解决这个问题,Redis提供了AOF文件重写的功能。通过这个功能,Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新AOF文件不会包含冗余命令。实现原理是从数据库中读取键当前的值,然后用生成一条命令去代替之前记录这个键值的多条命令。

例如:

实际执行命令
sadd animals "cat"
sadd animals "dog" "panda" "tiger"
srem animal "cat"
sadd animals "lion" "cat" 重写后保存命令
sadd animals "dog" "panda" "tiger" "lion" "cat"

另外AOF重写一般是使用子线程在后台执行,在重写期间服务器仍然继续处理客户端的请求。在重写期间,如果服务端处理的请求导致现有的数据库内容被修改,就会导致服务器当前的数据库状态与重写后的AOF文件保存的数据库状态不一致



为了解决这个问题,Redis服务器中设置了AOF重写缓冲区,会将AOF重写期间执行的写命令追加到AOF重写缓冲区中,等子线程重写完成后,再将缓冲区内容追加到AOF文件末尾,保持数据库状态一致

主从复制

Redis的复制功能分为同步和命令传播两个操作:

  • 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态
  • 命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态

这个复制功能对于初次复制来讲能够很好地完成任务,但是对于断线后重复制来说,有可能从服务器跟主服务器数据只发生了几次变化甚至完全一致,但这个复制却要重新全量的覆盖一遍从服务器,效率非常低。为此Redis在2.8版本后开始,改进了复制功能,适用PSYNC命令代替SYNC命令。

完整重同步和部分重同步

PSYNC命令分为完整重同步和部分重同步两种操作

  • 完整重同步:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步
  • 部分重同步:用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,主服务器将一部分最近传播的写命令保存在复制积压缓冲区中,如果从服务器的复制偏移量之后的数据仍然存在复制积压缓冲区中,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态



哨兵Sentinel

哨兵对redis服务器集群的监听



主观下线:Sentinel对redis服务节点默认每秒发送心跳检测节点是否在线,但Redis实例连续向Sentinel返回无效回复,该Sentinel节点会将实例标记为主观下线状态。

客观下线:当Sentinel将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线了,它会向同样监视这一主服务器的其它Sentinel进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。当Sentinel从其他Sentinel那里接收到足够数量的已下线判断后,Sentinel就会将主服务判定为客观下线,并对主服务执行故障转移。

执行者选举

Sentinel确认主服务已经客观下线后,会要求其他Sentinel节点将自己设为执行故障转移的节点,其他节点采用抢占的方式,只接受第一个到达的抢占请求,并返回当前节点认可的执行节点ID,通过统计,可以得到最终过半数胜出的领头Sentinel执行故障转移

故障转移

在选举产生出领头Sentinel之后,领头Sentinel将对已下线的主服务器执行故障转移操作,该操作包含以下三个步骤:

  1. 在已下线主服务器属下的所有从服务器中,挑选出一个从服务器,并将其转换为主服务器
  2. 让已下线主服务器属下的所有从服务器改为复制新的主服务器
  3. 将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,它就会成为新的主服务器的从服务器

选择新的主服务器流程

  1. 筛选出在线的从服务器
  2. 根据从服务器的优先级,对从服务器进行排序,选择优先级最高从服务器
  3. 同最高优先级的从服务器,选择复制偏移量最大的从服务器(保存着最新数据)
  4. 以上都相同时,选择服务器运行ID最小的从服务器

Redis设计的更多相关文章

  1. Redis设计与实现(一~五整合版)【搬运】

    Redis设计与实现(一~五整合版) by @飘过的小牛 一 前言 项目中用到了redis,但用到的都是最最基本的功能,比如简单的slave机制,数据结构只使用了字符串.但是一直听说redis是一个很 ...

  2. 《Redis设计与实现》读书笔记

    <Redis设计与实现>读书笔记 很喜欢这本书的创作过程,以开源的方式,托管到Git上进行创作: 作者通读了Redis源码,并分享了详细的带注释的源码,让学习Redis的朋友轻松不少: 阅 ...

  3. 重读redis设计与实现

    重读了一遍redis设计与实现,这次收获也不错,把之前还有些疑惑的点:redis跳跃表的原理.redis持久化的方法.redis复制.redis sentinel.redis集群等,都重新熟悉了一遍, ...

  4. 如何使用redis设计关系数据库

    目录 redis设计关系数据库 前言 设计用户信息表结构 hash存储记录 set存储id 图示 索引/查询: 1.select 查询所有记录 : 类似sql的select from table_na ...

  5. 《Redis设计与实现》

    <Redis设计与实现> 基本信息 作者: 黄健宏 丛书名: 数据库技术丛书 出版社:机械工业出版社 ISBN:9787111464747 上架时间:2014-6-3 出版日期:2014 ...

  6. 《Redis设计与实现》阅读笔记(一)--Redis学习

    Redis学习资料与过程记录 在实习中经常会用到很多Redis,对Redis有了一些模糊的了解,总觉得隔靴搔痒的不痛快,所以决定开始深入的了解Redis,也作为我实习期间的目标. 这篇只是为了占个位置 ...

  7. Redis设计与实现读后感

    看了一下时间,现在是2018年8月22日14:28,看完最后一页内容之后,我简短的停留了一下,任思绪翻飞. redis设计与实现大概看了有12天左右,12天前,我的心里很乱,整个人都处于一种焦虑不安的 ...

  8. 180713-Spring之借助Redis设计访问计数器之扩展篇

    之前写了一篇博文,简单的介绍了下如何利用Redis配合Spring搭建一个web的访问计数器,之前的内容比较初级,现在考虑对其进行扩展,新增访问者记录 记录当前站点的总访问人数(根据Ip或则设备号) ...

  9. 180626-Spring之借助Redis设计一个简单访问计数器

    文章链接:https://liuyueyi.github.io/hexblog/2018/06/26/180626-Spring之借助Redis设计一个简单访问计数器/ Spring之借助Redis设 ...

  10. 【Redis】四、Redis设计原理及相关问题

    (六)Redis设计原理及相关问题   通过前面关于Redis五种数据类型.相关高级特性以及一些简单示例的使用,对Redis的使用和主要的用途应该有所掌握,但是还有一些原理性的问题我们在本部分做一个探 ...

随机推荐

  1. Typora用法:

    Typora用法: 一:标题 模板: #+空格+标题名+回车 一级标题 二级标题 三级标题 四级标题 五级标题 二:字体 加粗 斜体 斜体加粗 删除线(esc键下面的那个键) 上标:我是上标 下表:我 ...

  2. js中 call()与apply()方法 和 bind()方法

    call与apply都属于Function.prototype(即原型对象身上的方法)的一个方法,所以每个function实例都有call.apply属性: call()和apply() 是静态方法, ...

  3. [OpenCV-Python] 13 颜色空间转换

    文章目录 OpenCV-Python:IV OpenCV中的图像处理 13 颜色空间转换 13.1 转换颜色空间 13.2 物体跟踪 13.3 怎样找到要跟踪对象的 HSV 值? OpenCV-Pyt ...

  4. 2021-05-21:给定一个数组arr,先递减然后递增,返回arr中有多少个绝对值不同的数字?

    2021-05-21:给定一个数组arr,先递减然后递增,返回arr中有多少个绝对值不同的数字? 福大大 答案2021-05-21: 双指针.左指针最左,符合条件时右移:右指针最右,符合条件时左移.左 ...

  5. Selenium - 元素定位(1) - 八种元素定位

    Selenium - 元素定位 八种元素定位 我们在做WEB自动化时,最根本的就是操作页面上的各种元素,而操作的基础便是元素的定位,只有准确地定位到唯一元素才能进行后续的自动化控制,下面将对各种元素定 ...

  6. mysql报错Unknown collation: utf8mb4_0900_ai_ci

    mysql报错Unknown collation: utf8mb4_0900_ai_ci 解决方案: 将文件内的所有 utf8mb4_0900_ai_ci 换成 utf8_general_ci utf ...

  7. React-hooks 父组件通过ref获取子组件数据和方法

    我们知道,对于子组件或者节点,如果是class类,存在实例,可以通过 React.createRef() 挂载到节点或者组件上,然后通过 this 获取到该节点或组件. class RefTest e ...

  8. 深入理解 python 虚拟机:破解核心魔法——反序列化 pyc 文件

    深入理解 python 虚拟机:破解核心魔法--反序列化 pyc 文件 在前面的文章当中我们详细的对于 pyc 文件的结构进行了分析,pyc 文件主要有下面的四个部分组成:魔术. Bite Filed ...

  9. ODOO13之二 Odoo 13开发之开发环境准备

    在更深入了解 Odoo 开发之前,我们应配置好开发环境并学习相关的基础管理任务.本文中,我们将学习创建 Odoo 应用所需用到的工具和环境配置.这里采用 Ubuntu 系统来作为开发服务器实例的主机, ...

  10. 手把手教你实战TDD

    1. 前言 领域驱动设计,测试驱动开发. 我们在<手把手教你落地DDD>一文中介绍了领域驱动设计(DDD)的落地实战,本文将对测试驱动开发(TDD)进行探讨,主要内容有:TDD基本理解.T ...