1.背景
众所周知 redis是一个内存数据库,所以他的运行效率特别高。但是也存在一个问题:因为内存中的数据不是持久的,所以当redis宕机或者关机重启,那内存中的数据就全部丢失了。
当然这肯定是不允许的,redis是具有持久化机制的,它会通过设置 以快照或者操作日志的形式将数据持久化到磁盘中。
根据持久化使用技术的不同,Redis 的持久化分为两种:RDB 与 AOF。
Redis 持久化也称为钝化,是指将内存中数据库的状态描述信息保存到磁盘中。只不过是不同的持久化技术,对数据的状态描述信息是不同的,生成的持久化文件也是不同的。但它们的作用都是相同的:避免数据意外丢失。通过手动方式,或自动定时方式,或自动条件触发方式,将内存中数据库的状态描述信息写入到指定的持久化文件中。当系统重新启动时,自动加载持久化文件,并根据文件中数据库状态描述信息将数据恢复到内存中,这个数据恢复过程也称为激活。这个钝化与激活的过程就是 Redis 持久化的基本原理。
不过从以上分析可知,对于 Redis 单机状态下,无论是手动方式,还是定时方式或条件触发方式,都存在数据丢失问题:在尚未手动/自动保存时发生了 Redis 宕机状况,那么从上次保存到宕机期间产生的数据就会丢失。不同的持久化方式,其数据的丢失率也是不同的。
需要注意的是,RDB 是默认持久化方式,但 Redis 允许 RDB 与 AOF 两种持久化技术同时开启,此时系统会使用 AOF 方式做持久化,即 AOF 持久化技术的优先级要更高。同样的道理,两种技术同时开启状态下,系统启动时若两种持久化文件同时存在,则优先加载 AOF持久化文件。
本本是以windows系统为例 Redis-x64-5.0.14.1
2.RDB
RDB,Redis DataBase,是指将内存中某一时刻的数据快照全量写入到指定的 rdb 文件的持久化技术。RDB 持久化默认是开启的。当 Redis 启动时会自动读取 RDB 快照文件,将数据从硬盘载入到内存,以恢复 Redis 关机前的数据库状态。
手动 save
找到安装目录下的 ↓↓↓↓↓↓↓↓ 双击即可
redis-server.exe
redis-cli.exe
通过在 redis-cli 客户端中执行 save 命令可立即进行一次持久化保存。save 命令在执行期间会阻塞 redis-server 进程,直至持久化过程完毕。而在 redis-server 进程阻塞期间,Redis不能处理任何读写请求,无法对外提供服务。看图 ↓↓↓↓↓↓↓↓
因为这里save执行过快 体现不出阻塞 所以就不做演示了。
手动 bgsave
通过在 redis-cli 客户端中执行 bgsave 命令可立即进行一次持久化保存。不同于 save 命令的是,正如该命令的名称一样,background save,后台运行 save。bgsave 命令会使服务器进程 redis-server 生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程中,不会阻塞 redis-server 进程对客户端读写请求的处理。看图 ↓↓↓↓↓↓↓↓
可以看到 background saving started 后台保存开始
查看持久化时间
通过 lastsave 命令可以查看最近一次执行持久化的时间,其返回的是一个 Unix 时间戳。
看图 ↓↓↓↓↓↓↓↓
自动条件触发
打开redis.config 找到 SNAPSHOTTING 就是 快照的意思 这个下面就是redis 的 自动条件触发 的一些配置
自动条件触发的本质仍是 bgsave 命令的执行。只不过是用户通过在配置文件中做相应的设置后,Redis 会根据设置信息自动调用 bgsave 命令执行
该配置用于设置快照的自动保存触发条件,即 save point,保存点。该触发条件是在指定时间段内发生了指定次数的写操作。
- save 3600 1 # 在 3600 秒(1 小时)内发生 1 次写操作
- save 300 100 # 在 300 秒(5 分钟)内发生 100 次写操作
- save 60 10000 # 在 60 秒(1 分钟)内发生 1 万次写操作
stop-writes-on-bgsave-error
用于指定在执行后台保存(bgsave)出错时是否停止写入操作。当这个选项被设置为 yes
时,表示如果后台保存操作出现错误,Redis 将停止接受写入操作,以避免数据丢失或不一致。
当然,如果 bgsave 命令后来可以正常工作了,Redis将自动允许再次写入。
rdbcompression
表示在生成 RDB 文件时会对数据进行压缩,以减少磁盘空间的占用。加速主从集群中从节点的数据同步。
rdbchecksum
从 RDB5 开始,RDB 文件的 CRC64 校验和就被放置在了文件末尾。这使格式更能抵抗 RDB文件的损坏 表示在生成 RDB 文件时会计算并存储校验和,以便在加载 RDB 文件时进行数据完整性检查。
RDB 文件结构
RDB 持久化文件 dump.rdb 整体上有五部分构成:
SOF
SOF 是一个常量,一个字符串 REDIS,仅包含这五个字符,其长度为 5。用于标识 RDB文件的开始,以便在加载 RDB 文件时可以迅速判断出文件是否是 RDB 文件。
rdb_version
这是一个整数,长度为 4 字节,表示 RDB 文件的版本号。
EOF
EOF 是一个常量,占 1 个字节,用于标识 RDB 数据的结束,校验和的开始。
check_sum
校验和 check_sum 用于判断 RDB 文件中的内容是否出现数据异常。其采用的是 CRC 校验算法。
CRC 校验算法:
在持久化时,先将 SOF、rdb_version 及内存数据库中的数据快照这三者的二进制数据拼接起来,形成一个二进制数(假设称为数 a),然后再使用这个 a 除以校验和 check_sum,此时可获取到一个余数 b,然后再将这个 b 拼接到 a 的后面,形成 databases。
在加载时,需要先使用 check_sum 对 RDB 文件进行数据损坏验证。验证过程:只需将RDB 文件中除 EOF 与 check_sum 外的数据除以 check_sum。只要除得的余数不是 0,就说明文件发生损坏。当然,如果余数是 0,也不能肯定文件没有损坏。
这种验证算法,是数据损坏校验,而不是数据没有损坏的校验。
对于 Redis 默认的 RDB 持久化,在进行 bgsave 持久化时,redis-server 进程会 fork 出一个 bgsave 子进程,由该子进程以异步方式负责完成持久化。而在持久化过程中,redis-server进程不会阻塞,其会继续接收并处理用户的读写请求。
bgsave 子进程的原理如下:
bgsave 子进程在持久化时首先会将内存中的全量数据 copy 到磁盘中的一个 RDB 临时文件,copy 结束后,再将该文件 rename 为 dump.rdb,替换掉原来的同名文件。
不过,在进行持久化过程中,如果 redis-server 进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块 copy 出一个副本。等内存中的全量数据 copy 结束后,会再将副本中的数据 copy 到 RDB 临时文件。
好了 RDB 就分享到这里 下期分享AOF
扩展
save m n原理
通过serverCron函数、dirty计数器、和lastsave时间戳来实现的
serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次 检查 save m n 配置的条件是否满足,如果满足就执行bgsave
dirty计数器是记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改;而当save/bgsave执行完成后,会将dirty重新置为0。
astsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间
每隔100ms,执行serverCron函数遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave
问题:save 300 100 五分钟 100次操作 进行bgsave 如果每五分钟99次多久执行bgsave
先比较时间 如果上次bgsave时间大于五分钟 比较次数 次数是99不执行bgsave
当五分钟之后 比如第六分钟执行的第100次 那么就是执行完第100次命令后的100ms执行bgsave 就是先比较时间 时间满足 比较次数 同时满足执行
当前时间-lastsave > m
dirty >= n
如果对RDB有更好了解 欢迎大家评论!