Redis基础知识(学习笔记15--持久化 (1))
一. 基础概览
1.1 两种方式
Redis具有持久化功能,其会按照设置以快照或操作日志的形式将数据持久化到硬盘。根据持久化使用技术的不同,Redis的持久化分为两种:RDB 和 AOF。
1.2 基本原理
Redis持久化也称为钝化,是指将内存中的数据库的状态描述信息保存到磁盘中。
1.3 加载
当胸痛重新启动时,自动加载持久化文件,并根据文件中数据库状态描述信息将数据恢复到内存中,这个数据恢复过程称为激活。
需要注意的是,RDB是默认持久化方式,但Redis允许RDB和AOF两种持久化技术同时开启。两种技术同时开启的状态下,系统启动时若两种持久化文件同时存在,则优先加载AOF持久化文件。
二. RDB 持久化
RDB,Redis DataBase,是指将内存中某一时刻的数据快照全量写入到指定rdb文件的持久化技术。RDB持久化默认是开启的。当Redis启动时会自动读取RDB文件,将数据从硬盘载入到内存,以恢复Redis数据。
2.1 持久化的执行
RDB持久化的执行有三种方式:手动save命令、手动bgsave,与自动条件触发。
(1)手动save命令
save
通过在redis-cli客户端中执行save命令,可立即进行一次持久化保存。save命令在执行期间会阻塞redis-server进程,直到持久化过程完毕。而在redis-server进程阻塞期间,redis不能处理任何读写请求,无法对外提供服务。
(2)手动bgsave
bgsave
通过在redis-cli客户端中执行bgsave命令,可立即进行一次持久化保存。不同于save命令的是,正如该命令的名称一样,background save,后台允许save。bgsave命令会使服务器进程redis-server生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程中,不会阻塞redis-server进程对客户端读写请求的处理。
(3)自动条件触发
自动条件触发的本质仍是bgsave命令的执行。只不过是用户通过在配置文件中做相应的设置后,redis会根据设置信息自动调用bgsave命令执行。
(4)查看持久化时间
通过lastsave命令可以查看最近一次执行持久化的时间,其返回的是一个Unix时间戳。
lastsave
2.2 RDB优化配置
RDB相关的配置在redis.conf文件中的SNAPSHOTTING部分。
################################ SNAPSHOTTING ################################ # Save the DB to disk. # # save <seconds> <changes> [<seconds> <changes> ...] # # Redis will save the DB if the given number of seconds elapsed and it # surpassed the given number of write operations against the DB. # # Snapshotting can be completely disabled with a single empty string argument # as in following example: # # save "" # # Unless specified otherwise, by default Redis will save the DB: # * After 3600 seconds (an hour) if at least 1 change was performed # * After 300 seconds (5 minutes) if at least 100 changes were performed # * After 60 seconds if at least 10000 changes were performed # # You can set these explicitly by uncommenting the following line. # 下面是默认持久规则 # save 3600 1 300 100 60 10000
# 如果60s内执行了10000次的变更操作,则执行一次bgsave;如果这个条件不成立,例如,60s内就执行了9990次, 那么就检查300s内,是否变化了100次+,如果满足,则bgsave
# 一次;如果还是不满足,例如 5分钟(300s),就执行了99次,那么怎看上面的规则;判断 3600s,变化次数是否不小于1次(至少一次),如果至少一次,则触发 bgsave。
# 即:这儿定义的触发 持久化的条件:依次判断 【60 10000】?【300 100】? 【3600 1】? 。要求是越来越低了。
# By default Redis will stop accepting writes if RDB snapshots are enabled # (at least one save point) and the latest background save failed. # This will make the user aware (in a hard way) that data is not persisting # on disk properly, otherwise chances are that no one will notice and some # disaster will happen. # # If the background saving process will start working again Redis will # automatically allow writes again. # # However if you have setup your proper monitoring of the Redis server # and persistence, you may want to disable this feature so that Redis will # continue to work as usual even if there are problems with disk, # permissions, and so forth. stop-writes-on-bgsave-error yes ## 上面的参数 是 bgsave 遇到错误时,是否阻止写入的参数
# Compress string objects using LZF when dump .rdb databases? # By default compression is enabled as it's almost always a win. # If you want to save some CPU in the saving child set it to 'no' but # the dataset will likely be bigger if you have compressible values or keys. rdbcompression yes ##是否采用压缩的参数
# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. # This makes the format more resistant to corruption but there is a performance # hit to pay (around 10%) when saving and loading RDB files, so you can disable it # for maximum performances. # # RDB files created with checksum disabled have a checksum of zero that will # tell the loading code to skip the check. rdbchecksum yes ##备份校验的参数
# Enables or disables full sanitization【净化;消毒;卫生处理;】 checks for ziplist and listpack etc when # loading an RDB or RESTORE payload. This reduces the chances of a assertion or # crash later on while processing commands. # Options: # no - Never perform full sanitization # yes - Always perform full sanitization # clients - Perform full sanitization only for user connections. # Excludes: RDB files, RESTORE commands received from the master # connection, and client connections which have the # skip-sanitize-payload ACL flag. # The default should be 'clients' but since it currently affects cluster # resharding via MIGRATE, it is temporarily set to 'no' by default. # # sanitize-dump-payload no # The filename where to dump the DB dbfilename dump.rdb # Remove RDB files used by replication in instances without persistence # enabled. By default this option is disabled, however there are environments # where for regulations【法规;规则;章程】 or other security concerns【忧虑;担心】, RDB files persisted on # disk by masters in order to feed replicas, or stored on disk by replicas # in order to load them for the initial synchronization, should be deleted # ASAP【as soon as possible】. Note that this option ONLY WORKS in instances that have both AOF # and RDB persistence disabled, otherwise is completely ignored.--注意生效的前提。 # # An alternative (and sometimes better) way to obtain the same effect is # to use diskless replication on both master and replicas instances. However # in the case of replicas, diskless is not always an option. rdb-del-sync-files no # The working directory. ##这一part是说设置目录的 # # The DB will be written inside this directory, with the filename specified # above using the 'dbfilename' configuration directive. # # The Append Only File will also be created inside this directory. ##注意:对AOF文件(备份方式)同样有用 # # Note that you must specify a directory here, not a file name. dir ./ ################################# REPLICATION #################################
需要说明的是,下面这语句比较考验 英语 能力。
By default this option is disabled 【默认是关闭的】, however there are environments where for regulations or other security concerns 【但是考虑的一些要求】,
RDB files 【【【 persisted on disk by masters in order to feed replicas, or stored on disk by replicas in order to load them for the initial synchronization 这些都是定语,
是用来描述 RBD file 的 用途,在master是什么用途,在replica上什么用途】】】, should be deleted ASAP.
2.3 RDB文件结构
RDB持久化文件dump.rdb整体上有五部分构成:
(1)SOF
SOF(Start Of File)是一个常量,一个字符串REDIS,仅包含这5个字符,其长度为5.用于标识RDB文件的开始,以便在加载RDB文件时可以迅速判断出文件是否是RDB文件。
(2)rdb_version
这是一个整数,长度为4字节,表示RDB文件的版本号。
(3)EOF
EOF(End Of File)是一个常量,占1个字节,用于标识RDB数据的结束,校验和开始。
(4)check_sum
校验和check_sum用于判断RDB文件中的内容是否出现数据异常。其采用的是CRC校验算法。
CRC 校验算法:
在持久化时,先将SOF、rdb_version及内存数据库中的数据快照,这三者的二进制数据拼接起来,形成一个二进制数据(假设称为数据a),然后再使用这个除以校验和check_sum,此时可获取到一个余数b,然后再将b 拼接到a的后面,形成了databases。----这样说应该不对吧?应该说形成了SOF+rdb_version+databases的结构体。
再加载时,需要先使用check_sum,对RDB文件进行数据情况判断(是否损坏)。验证过程为:只需将RDB文件中除EOF与check_sum外的数据除以check_sum,只要除得到余数不是0,就说明文件发生了损坏。当然,如果余数是0,也不能肯定文件没有损坏。
(5)databases
databases部分是RDB文件中最重要的数据部分,其可以包含任意多个非空数据库。而每个database又是由三部分构成:
*** SODB:是一个常量,占1个字节,用于标识一个数据库的开始。
*** db_number:数据库编号。
*** key_value_pairs:当前数据库中的键值对数据。
每个key_value_pairs又由很多个用于描述键值对的数据构成。
*** VALUE_TYPE:是一个常量,占1个字节,用于标识该键值对中value的类型。
*** EXPIRETIME_UNIT:是一个常量,占1个字节,用于标识过期时间的单位是秒还是毫秒。
*** time:当前key-value的过期时间。
概况总结如下
2.4 RDB持久化过程
对于Redis默认的RDB持久化,在进行bgsave持久化时,redis-save进程会fork出一个bgsave子进程,由该子进程以异步方式负责完成持久化。而在持久化过程中,redis-server进程不会阻塞,其会继续接收并处理用户的读写请求。
bgsave子进程详细工作原理如下:
由于子进程可以继承父进程的所有资源,且父进程不能拒绝子进程的继承权。所以,bgsave子进程有权读取到redis-server进程写入到内存中的用户数据,使得将内存数据持久化到dump.rdb称为可能。
bgsave子进程在持久化时首先会将内存中的全量数据copy到磁盘中的一个RDB临时文件,copy结束后,再将该文件rename为dump.rdb,替换掉原来的同名文件。
不过,在进行持久化过程中,如果redis-server进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块copy出一个副本。等内存中的全量数据copy结束后,会再将副本中的数据copy到RDB临时文件。这个副本的生成是由Linux系统的写时复制技术(Copy-On-Write)实现的。
概况总结如下
内容补充--写时复制
写时复制技术是LInux系统的一种进程管理技术。
原本再Unix系统中,当一个主进程通过fork()系统调用创建子进程后,内核进程会复制主进程的整个内存空间中的数据,然后分配给子进程。这中方式存在的问题由以下几点:
(1)过程非常耗时;(2)过程降低了系统性能;(3)如果主进程修改了内存数据,子进程副本中的数据是没有修改的。即出现了数据冗余,而冗余数据最大的问题是数据一致性无法保证。
现代的Linux则采用了更为有效的方式:写时复制。子进程会继承父进程的所有资源,其中就包括主进程的内存空间。即子进程和父进程共享内存。只要内存被共享,那么该内存就是只读的(写保护的)。而写时复制则是在任何一方需要写入数据到共享内存时就会出现异常,此时内核进程就会将需要写入的数据copy出一个副本写入到另一块非共享内存区块。
在写时复制的视角下,看bgsave,如下:
学习参阅声明
【Redis视频从入门到高级】
【https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】