Redis单机数据库的实现1

前言

Redis系列博客为对黄健宏老师《Redis设计与实现》一书内容的整理

第9章 数据库

服务器中的数据库

Redis服务器通过db数组来保存redis数据库

默认情况下,Redis客户端的目标数据库为0号数据库,但客户端可以通过执行select命令来切换目标数据库

select操作会更新redisClient(客户端)db属性指针指向的数据库内容

数据库键空间

Redis是一个键值对数据库服务器,redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间。

键空间和用户所见的数据库时直接对应的:

* 键空间的键也就是数据库的键,每个键都是一个字符串对象

* 键空间的值也就是数据库的键,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种Redis对象。

键空间的键并不都是永久保存的,用户可以人为指定键的过期时间等信息。

过期键删除策略

如果一个键过期了,那么它什么时候会被删除呢?

这个问题有三种可能的删除策略:

1、定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作

优点:对内存最友好,可以及时删除不需要的键

缺点:对CPU时间最不友好,删除过期键这一行为可能会占用相当一部分的CPU时间,在内存不紧张但是CPU时间紧张的情况下,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。

2、惰性删除:放任键过期不管,但是每次从键空间中获取键时,都会检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键

优点:对CPU时间来说最友好,只有取出键时才会进行检查,而不会花费大量时间集中式检查键的过期情况消耗CPU时间

缺点:对内存最不友好。如果一直不用一个键,那这个键就会一直存储在内存里。我们甚至可以将这种情况视为内存泄露

3、定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少个过期键,以及要检查多少个数据库,则由算法决定。

定期删除是对前两种策略的一种这种,如果采用定期删除策略的话,服务器必须根据情况,合理设置删除操作的执行时长和执行频率。(定期也不代表一次删除全部键,而是一次删除一小部分过期键,多批次执行

随机检查一部分键来减少CPU时间消耗

Redis的过期键删除策略

Redis服务器实际使用的是惰性删除和定期删除两种策略,通过配合使用这两种删除策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。

数据库通知

数据库通知功能可以让客户端通过订阅给定的频道或者模式,来获知数据库中键的变化,以及数据库中命令的执行情况。

另一类通知被称为“键空间通知”,关注的是“某个命令被什么键执行”

第10章 RBD持久化

Redis服务器中通常包含着任意个非空数据库,而每个非空数据库中又包括任意个键值对。我们将服务器中的非空数据库以及他们的键值对统称为数据库状态。

以为Redis是内存数据库,它将自己的数据库状态储存在内存里面(因此一个redis能储存的数据也就内存大小,比较小,需要通过集群来落地使用),所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。

为了解决这个问题,Redis提供了RDB持久化功能,可以手动或定期将当前时间点的数据保存到RDB文件中。

RDB文件是一个经过压缩的二进制文件

RDB文件的创建与载入

有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE。

SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止。

BGSAVE命令则会派生出一个自己才能拿,然后由子进程负责创建RDB文件。

和创建RDB文件不同,RDB文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入RDB文件的命令。

值得一提的是,因为AOF文件的更新频率通常比RDB文件的更新频率高,所以

* 如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原服务器状态

* 只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态

自动间隔性保存

因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行依次BGSAVE命令。

另外执行BGSAVE有时需要设置保存条件,这个条件和dirty计数器以及lastsave有关,判断一定时间内修改的次数来确定是否保存。(没有更改没必要保存)

保存始终存在着一定时间间隔,无法实时保存内容,不可避免会出现内容遗漏的情况。

第11章 AOF持久化

除了RDB持久化功能外,Redis还提供了AOF(Append Only File)持久化功能。

与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。

举例而言,对于

SADD fruits "apple" "banana" "cherry"

 语句而言,RDB持久化保存数据库状态的方法是将键值对保存起来,AOF持久化保存的方法则是将服务器执行的命令保存到AOF文件中。

AOF持久化的实现

AOF持久化功能的实现可以分为命令追加、文件写入、文件同步三个步骤。

命令追加

当AOF持久化功能处于打开状态时,服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。

AOF文件的写入与同步

Redis的服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接受客户端的命令请求,以及向客户端发送命令恢复,而时间事件则负责执行像serverCron函数这样需要定时运行的函数。

写入:将内存中aof_buf的内容写入到os的buf里

通常等缓存填满或者超过指定时间才同步到磁盘

同步:将os buf里的内容同步保存到磁盘上

时间和频率需要根据实际需要来确定

AOF文件的载入和数据还原

服务器只需要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。

Redis读取AOF文件并还原数据库状态的具体步骤如下:

1、创建一个不带网络连接的伪客户端,这个客户端依次发起写命令请求

2、Redis按照标准流程执行这些写命令

AOF重写

AOF文件记录了写命令,所以随着服务器运行时间的流失,AOF文件中的内容会越来越多。并且随着AOF文件的体积增大,AOF进行数据还原所需要的时间也就越多。

为了解决AOF文件体积膨胀的问题,Redis提供了AOF文件重写(rewrite)功能。通过该功能,Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库状态相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新AOF文件的体积会比旧AOF文件的体积小得多。

创建新文件——注入内容——改名——删除旧文件

具体流程:识别数据库状态(全部键值对)——为每个键值对匹配对应的写指令

因为新的AOF文件只包含还原当前数据库状态所必须的命令,所以新AOF文件不会浪费任何硬盘空间。

AOF后台重写

为了避免重写AOF文件期间,服务器无法处理客户端发来的命令请求,Redis决定将AOF重写程序放到子进程里执行,这样做有以下两个好处:

* 子进程进行AOF重写期间,父进程可以继续处理命令请求

* 子进程带有服务器进程的数据副本,可以避免加锁来保证数据安全性。

如果在重写期间发来命令,这个命令会同时被写入AOF缓冲区和AOF重写缓冲区,尽量保证新旧两个文件效果一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值