Redis-持久化之RDB 持久化基本原理Redis持久化也称钝化指将内存中数据库的状态描述信息保存到磁盘。可以通过手动、自动定时、自动条件触发等方式将内存中数据保存到持久化文件。当系统重启后自动加载持久化文件根据文件中的信息将数据恢复到内存中这个恢复过程称为激活。这个钝化与激活的过程就是持久化的基本原理。注意Redis单机状态下无论哪种触发方式都存在数据丢失问题在未保存数据到内存时发生了宕机那么从上次保存到宕机期间产生的数据就会丢失。不同的持久化方式数据的丢失率不同。RDB是Redis默认持久化方式但Redis允许RDB与AOF同时开启。此时系统会使用AOF做持久化即AOF的优先级更高。也就是同时开启状态下系统启动时若两种持久化文件同时存在则优先加载AOF持久化文件。RDB持久化RDB Redis DataBase指将内存中某一时刻的数据快照全量写入到指定的rdb文件的持久化技术。RDB默认开启。当Redis启动时会自动读取RDB快照文件将数据从硬盘载入到内存以会Redis关机前的数据库状态。持久化的执行RDB持久化执行有三种方式手动save命令、手动bgsave命令、自动条件触发。手动save命令注意此命令在执行期间会阻塞Redis进程直至执行完毕。在Redis阻塞期间Redis无法执行任何读写操作无法对外提供服务。手动bgsave命令bgsave backgroud save命令可立即进行一次持久化保存。不同于save命令bgsave 后台允许save。bgsave 会使服务器进程生成一个子进程由这个子进程完成保存在子进程执行期间不会阻塞Redis进程。自动条件触发自动条件触发本质仍是bgsave命令只不过是通过在品牌配置文件中做相应的设置后Redis会根据设置辛纳希自动调用bgsave命令执行。查看持久化时间执行lastsave命令可以查看最近一次执行持久化的时间返回的是一个Unix时间戳。RDB优化配置RDB的相关配置在redis.conf文件的SNAPSHOTTING部分。save该配置用于设置自动保存触发条件即save point 保存点。该触发条件指规定时间发生了指定次数的写操作。默认的持久化条件是save 3600 1 300 100 60 10000.其意思是save 3600 1 # 在3600秒内1小时发生1次写操作 save 300 100 # 在300秒内5分钟发生100次写操作 save 60 10000 # 在60秒内1分钟发生10000次写操作如果不启用RDB持久化设置save的参数为空串即可save “”注意这个配置虽然以save开头实际执行的是bgsave命令。stop-write-on-bgsave-error默认情况下RDB快照已启用至少一个保存点且最近的bgsave命令失败Redis将停止接收写入。这样设置的目的是让用户意识到数据没有正确的保存到磁盘上否则可能会发生一些灾难。如果bgsave命令后来正常工作了Redis自动允许再次写入。默认配置如下stop-write-on-bgsave-error yesrdbcompressionrdbcompression 的作用是进行持久化时启用LZF压缩字符串对象。虽然压缩RDB文件会消耗系统资源但可以大幅降低文件大小方便保存到磁盘加速主从集群中从节点的数据同步。rdbcompression yesrdbchecksumRDB文件的CRC64校验和放置在了文件末尾。这使个格式更能抵抗RDB文件的虽坏但在保存和加载RDB文件时性能会受到影响。因此可以设置为no禁用校验和以获得最大性能。这样会告诉加载代码跳过校验检查。默认yes开启校验功能。rdbchecksum yessanitize-dump-payload此配置用于设置在加载RDB文件或进行持久化时是否开启对zipList、listPack等数据的全面安全检测。检测可以降低命令处理时系统崩溃的可能。其可选值有三种no不检测yes总是检测clients只有当客户端连接时才检测。排除了加载RDB文件时和持久化时的检测。默认值为no不检测。dbfilename指定RDB文件名称默认为dump.rdbdbfilename dump.rdbrdb-del-sync-files主从复制时是否自动删除同步的从机上的RDB文件。默认是no不删除。注意只有从机的RDB和AOF持久化功能都未开启时才生效。dir指定RDB和AOF文件的生成目录默认时Redis安装的根目录。dir ./RDB文件结构RDB持久化文件dump.rdb由五部分构成SOFSOF是一个常量一个字符串REDIS仅包含这5个字符长度为5.用于表示RDB文件的开始以便在加载RDB文件时可以迅速判断出文件是否是RDB文件。rdb_version这是一个整数长度为4字节表示RDB文件的版本号。EOFEOF是一个常量占1个字节用于标识RDB数据的结束校验和的开始。check_sumcheck_sum校验和用于判断RDB文件中的内容是否出现数据异常。采用的是CRC校验算法。CRC校验算法 在持久化时先将SOF、rdb_version及内存数据库里的数据快照这三者的二进制数据拼接起来。 形成一个二进制数假设为a然后将a除以check_sum得到余数b再将b拼接到a后面形成database。 加载时先使用check_sum对RDB文件进行数据损坏验证。过程如下 将RDB文件中除EOF和check_sum外的数据除以check_sum。只要余数0就说明文件已损坏。当然如果余数是0也不能肯定文件没有损坏。 这种验证算法是数据损坏校验而不是数据没有损坏的校验。databasedatabase是RDB文件中最重要的数据部分包含任意多个非空数据库。每个database由三部分组成SODB一个常量占1字节标识一个数据库的开始db_number:数据库编号key_values_pairs当前数据库中键值对的数据。每个key_values_pairs由很多个用于描述键值对的数据组成VALUE_TYPE一个常量。占1个字节标识键值对中value的类型EXPTRETIME_UNIT一个常量占1个字节标识过期时间的单位是秒还是毫秒time当前key-value的过期时间。RDB持久化过程RDB在进行bgsave持久化时redis-server进程会fork一个子进程以异步方式完成持久化期间redis-server进程不会阻塞会继续接收并处理用户的读写请求。bgsave子进程的工作原理如下​ 子进程会继承父进程的资源先将内存中全量数据copy到一个RDB临时文件copy结束后将该文件rename为dump.rdb替换掉原来的同名文件。​ 不过在持久化过程中如果redis-server进程接收到了读写请求。系统会将发生数据修改的物理块copy出一个副本等全量数据copy结束后再将副本中的数据copy到RDB临时文件。这个副本的生成是由Linux系统的写时复刻技术copy-on-write实现的。写时复刻子进程会继承父进程的所有资源其中包括主进程的内存空间。及子进程和父进程共享内存。只要内存被共享那么该内存就是只读的写保护的。而写时复刻是在任何一方需要写入数据到共享内存时都会出现异常。此时内核进程会将需要写入的数据copy出一个副本写入到另外一块非共享内存区域。