前言

参考资料:《Redis设计与实现 第二版》;

第二部分为单机数据库的实现,主要由以下模块组成:数据库持久化事件客户端服务器

本篇将介绍 Redis 中的数据库;


1. Redis中的数据库

  • Redis服务器的所有数据库保存在redis.h/redisService结构的db数组中:

    struct redisService{
    //...
    //保存所有数据库的数组
    redisDB *db; //服务器的数据库数量
    int dbnum;
    //...
    }
    • dbnum属性由服务器配置的 database 选项决定,默认为 16;
  • Redis客户端数据库保存在在redisClient结构的db属性:

    typedef struct redisClient{
    //...
    //记录客户端当前正在使用的数据库
    redisDB *db;
    } redisClient;
    • 客户端通过修改目标数据库指针,让它指向 redisService.db 数组中的不同元素;
    • 可以通过 SELECT index 命令来切换数据库;

  • 数据库的定义在redis.h/redisDb结构中:

    typedef struct redisDb{
    //...
    //数据库键空间,保存数据库中所有的键值对
    dict *dict; //过期字典,保存着键的过期时间
    dict *expires;
    } redisDb;
    • 键空间的键是数据库的键,每个键是一个字符串对象;
    • 键空间的值是数据库的值,每个值可以是字符串对象列表对象哈希表对象集合对象有序集合对象中的一种;

2. 数据库的键空间

  • 数据库键空间是一个字典,所有针对数据库的操作都是通过键空间字典来操作的;
  • 在对键空间进行读写操作时,Redis 还会进行一些维护操作:
    • 读取键后,会根据键是否存在更新服务器的键空间命中 keyspace_hits 次数或键空间不命中 keyspace_misses 次数。通过 INFO stats 命令查看属性;
    • 读取键后,服务器会更新键的 LRU(最后一次使用时间)。通过 ONBJECT idlettime [key] 命令查看key的闲置时间;
    • 服务器在读取键时发现键已经过期,会先删除这个过期键;
    • 如果有客户端使用 WATCH 命令监视某个键,服务器对该键修改后会标记上脏 dirty,让事务处理程序注意;
    • 服务器每修改一个键后,会对脏 dirty 键计数器值增 1,计数器会触发服务器的持久化以及复制操作;

3. 键的生成时间与过期时间

  • 键的时间相关设置命令参看《Redis常用命令及示例总结》1.3 生存时间的功能
  • 生存时间:
    • 客户端可以通过 EXPIREPEXPIRE 命令以秒或毫秒精度为数据库中某个键设置生存时间(Time To Live,TTL)。经过指定时间后,服务器自动删除生存时间为0的键;
    • 可以通过 SETEX 命令在设置字符串键同时设置过期时间;
    • 使用 TTLPTTL 命令获取键的剩余生存时间;
  • 过期时间:
    • 客户端设置过期时间的命令是 EXPIREATPEXPIREAT
    • 过期时间是一个 UNIX 时间戳;
  • EXPIREPEXPIREEXPIREAT 三个命令都会转换成 PEXPIREAT 命令实现;

4. Redis中的过期键删除策略

  • 有三种删除过期键的策略:

    • 定时删除:主动策略。对内存最友好,到期就释放内存。缺点是对CPU事件不友好,当过期键比较多时,会占用一部分CPU时间;
    • 惰性删除:被动策略。对CPU时间最友好。每次从键空间获取键时,检查取得的键是否过期,过期则删除。缺点是对内存不友好;
    • 定期删除:主动策略。前两种策略的整合与折中。每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长与频率减少删除操作对CPU时间的影响。缺点是难以确定删除操作执行的时长和频率;
  • 惰性删除策略由 db.c/expireIfNeeded 函数实现,流程如下:

  • 定期删除策略由 redis.c/activeExpireCycle 函数实现,每当Redis的服务器周期性操作 redis.c/serverCron 函数执行时,activeExpireCycle 函数会被调用。在规定的时间内,分多次遍历服务器各个数据库,从数据库的 expires 字典中随机检查一部分过期时间,删除其中过期键;

5. AOF、RDB和复制功能对过期键的处理

5.1 生成 RDB 文件

  • 在执行 SAVEBGSAVE 命令创建一个新的 RBG 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的 RDB 文件中;

5.2 载入 RDB 文件

  • 载入 RDB 文件时:

    • 若服务器以主服务器模式运行,过期键不载入;
    • 若服务器以从服务器模式运行,所有键都会载入;

5.3 AOF 文件写入

  • 当服务器以 AOF 持久化模式运行时,未被惰性删除和定期删除的过期键不会对 AOF 文件产生影响;
  • 当过期键被惰性删除或定期删除后,程序会向 AOF 文件追加(append)一条 DEL 命令,显示记录该键已被删除;

5.4 AOF 重写

  • 与 RDB 文件类似,在执行 AOF 重写过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中;

5.5 复制

  • 当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制;



6. 数据库通知

  • 数据库通知是 Redis 2.8 版本新增的功能;
  • 数据库通知可以让客户端通过订阅给定的频道或模式,来获知数据库中键的变化,以及数据库中命令的执行情况;
  • Redis 命令对数据库进行修改后,服务器会根据配置向客户端发送数据库通知;
  • 通知的相关命令可以参考 《Redis常用命令及示例总结》7. Pub/Sub(发布/订阅)
  • 两类通知类型:
    • 键空间通知 key-space notification:关注 “某个键执行了什么命令”;SUBSCRIBE channel:message
    • 键事件通知 key-event notification:关注 “某个命令被什么键执行了”;SUBSCRIBE channel:del
  • 服务器配置的 notify-keyspace-events 选项决定服务器所发送通知的类型:
    • AKE:发送所有类型的键空间和键事件通知;
    • AK:发送所有类型的键空间通知;
    • AE:发送所有类型的键事件通知;
    • K$:只发送字符串有关的键空间通知;
    • EL:只发送列表键有关的键事件通知;
  • 发送数据库通知的功能是由 notify.c/notifyKeyspaceEvent 函数实现;

最后

新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!

Redis | 第4章 Redis中的数据库《Redis设计与实现》的更多相关文章

  1. Redis | 第11章 服务器的复制《Redis设计与实现》

    目录 前言 1. 旧版复制功能的实现 1.1 同步与命令传播 1.2 旧版复制功能的缺陷 2. 新版复制功能的实现 2.1 部分重同步的实现原理 3. PSYNC 命令的实现 4. 复制的详细步骤 4 ...

  2. Redis | 第12章 Sentinel 哨兵模式《Redis设计与实现》

    目录 前言 1. 启动并初始化 Sentinel 2. Sentinel 与服务器间的默认通信 2.1 获取主服务器信息 2.2 获取从服务器信息 2.3 向主服务器和从服务器发送信息 3. 接受来自 ...

  3. 我的Android六章:Android中SQLite数据库操作

    今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...

  4. Redis 数据恢复方法,redis-port 工具将自建 redis 的 rdb文件同步到云数据库

    1. Redis 恢复的机制 如果只配置 AOF ,重启时加载 AOF 文件恢复数据: 如果同时配置了 RDB 和 AOF ,启动是只加载 AOF 文件恢复数据: 如果只配置 RDB,启动是将加载 d ...

  5. Redis Installation、Configuration、Program Based On Redis Learning

    目录 . Redis 简介 . Redis安装配置 . 编程使用Redis . 使用Lua脚本 1. Redis 简介 0x1: Redis是什么 Redis是一款Nosql类型的基于key-valu ...

  6. Android中SQLite数据库小计

    2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...

  7. 一篇文章带你了解NoSql数据库——Redis简单入门

    一篇文章带你了解NoSql数据库--Redis简单入门 Redis是一个基于内存的key-value结构数据库 我们会利用其内存存储速度快,读写性能高的特点去完成企业中的一些热门数据的储存信息 在本篇 ...

  8. PHP中的数据库三、redis

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  9. [转]Node.js中koa使用redis数据库

    本文转自:https://blog.csdn.net/offbye/article/details/52452322 Redis是一个常用的Nosql数据库,一般用来代替Memcached做缓存服务, ...

随机推荐

  1. 洛谷3783 SDOI2017 天才黑客(最短路+虚树+边转点+线段树优化建图)

    成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...

  2. 洛谷3348 大森林 (LCT + 虚点 + 树上差分)

    这可真是道神仙题QWQ问了好多\(dalao\)才稍微明白了一丢丢做法 首先,我们假设不存在\(1\)操作,那么对于询问的一段区间中的所有的树,他们的形态应该是一样的 甚至可以直接理解为\(0\)操作 ...

  3. MyBatis概念和”安装“

    MyBatis概念 MyBatis的前身就是iBatis,本是apache的一个开源项目,2010年这个项目由apahce sofeware foundation 迁移到了google code,并且 ...

  4. C 标准库函数手册摘要

    <stdlib.h> int abs( int value ); long int labs( long int value ); 返回参数的绝对值 int rand( void ); v ...

  5. 工作3年的Java程序员,轻松拿到阿里P6Offer,只因为他搞明白了Redis这几个问题!!

    Redis中的多路复用模型 Redis6用到了多线程?那多线程应用在哪些地方,引入多线程后,又改如何保证线程安全性呢? 同时,如何在性能和线程安全性方面做好平衡? 关于Redis的单线程模型 在Red ...

  6. 《手把手教你》系列技巧篇(三十三)-java+ selenium自动化测试-单选和多选按钮操作-上篇(详解教程)

    1.简介 在实际自动化测试过程中,我们同样也避免不了会遇到单选和多选的测试,特别是调查问卷或者是答题系统中会经常碰到.因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助 ...

  7. 【c++ Prime 学习笔记】目录索引

    第1章 开始 第Ⅰ部分 C++基础 第2章 变量和基本类型 第3章 字符串.向量和数组 第4章 表达式 第5章 语句 第6章 函数 第7章 类 第 Ⅱ 部分 C++标准库 第8章 IO库 第9章 顺序 ...

  8. Noip模拟81 2021.10.20

    T1 语言 比较简单的题,然后就瞎写了,所以考场上就我一个写了线段树的,所以我的常数.... 所以就枚举动词的位置,找前面后面有没有出现$4$即可 1 #include<bits/stdc++. ...

  9. hdu 5101 Select (二分+单调)

    题意: 多多有一个智商值K. 有n个班级,第i个班级有mi个人.智商分别是v1,v2,.....vm. 多多要从这些人中选出两人.要求两人智商和大于K,并且两人不同班.问总共有多少种方案. 数据范围: ...

  10. Linux 服务器的基本性能及测试方法

    1. 摘要 一个基于 Linux 操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要,尤其当程序非正常工作 ...