相关文章:
众所周知,Redis 的数据都是存放在内存当中的,如果没有配置持久化,当 Redis 重启后数据就会全部丢失,因此我们需要开启 Redis 的持久化功能,在这里我们先来了解下其中的一种方式:RDB
一、RDB
-
RDB (Redis DataBase)
-
在指定时间间隔内,将内存中的数据保存到磁盘中,对应产生的数据文件默认为 dump.rdb
-
当需要恢复数据时,可以直接将快照文件加载进内存中,来达到恢复数据的目的
-
-
如何持久化
-
Redis 会单独创建 (fork) 一个子进程来进行持久化,会先将数据写入到一个临时 RDB 文件中,待持久化过程结束后,再用临时 RDB 文件替换原有的 RDB 文件
-
在此过程中,子进程负责 IO 操作,主进程仍然负责处理客户端的请求,从而保证了 Redis 的高性能
-
-
优势
-
在进行大规模数据恢复时,RDB 要比 AOF 恢复速度快
-
非常适合于文件备份,比如:我们可以在最近的24小时内,每小时备份一次 RDB 文件,或者在每个月的每一天,备份一次 RDB 文件,这样的话,当我们程序出现问题时,可以很容易地还原到不同的版本
-
非常适合于灾难恢复,我们可以轻松地将 RDB 文件压缩后转移到其他存储介质上
-
会单独创建一个子进程来进行持久化,子进程负责 IO 操作,主进程仍然负责处理客户端的请求,从而保证了 Redis 的高性能
-
-
劣势
-
由于 RDB 每隔一段时间才会进行持久化,因此在这段时间内,万一服务器出现问题宕机了,那么 Redis 就会丢失这一段时间内的所有数据,所以如果我们想要最大限度地避免数据丢失,那么 RDB 将不是一个很好的选择
-
由于 RDB 是通过创建 (fork) 一个子进程来进行持久化工作,因此当数据集十分庞大时,创建 (fork) 子进程的操作将是非常耗时的,会使 Redis 服务出现卡顿现象
-
二、RDB 相关配置
-
save
################################ SNAPSHOTTING ################################ # # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # Note: you can disable saving completely by commenting out all "save" lines. # # It is also possible to remove all the previously configured save # points by adding a save directive with a single empty string argument # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000
-
配置说明
指令 作用 save 900 1 如果 900 秒内至少有 1 个 key 的值发生改变,则保存 save 300 10 如果 300 秒内至少有 10 个 key 的值发生改变,则保存 save 60 10000 如果 60 秒内至少有 10000 个 key 的值发生改变,则保存 -
如果想禁用 RDB 配置,只需要在上面配置最后一行加上
save ""
即可
-
-
stop-writes-on-bgsave-error
# 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
-
当 stop-writes-on-bgsave-error 设置为 yes 时,表示当备份进程出错时,主进程就会停止接收写入操作,从而保证了持久化数据的一致性
-
当然,如果我们的业务有完善的监控系统,则可以禁止此项配置,没有的话,还是建议开启
-
-
rdbcompression
# Compress string objects using LZF when dump .rdb databases? # For default that's set to 'yes' 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
-
当 rdbcompression 设置为 yes 时,表示在备份的时候,需要将 RDB 文件进行压缩后再进行保存
-
这里建议将其设置为 no,因为 Redis 本身属于 CPU 密集型服务器,再开启压缩,会带来更多的 CPU 消耗,相比硬盘成本,CPU 性价比更高
-
三、save 与 bgsave 的区别
-
在 Redis 中,save、bgsave 都可用于指定 RDB 文件的同步策略,两者区别如下
-
save
- save 指令会阻塞 Redis 的主进程,直到 RDB 文件被创建完为止 (一般很少使用)
-
bgsave
-
bgsave 指令会创建 (fork) 一个子进程来创建 RDB 文件,不会阻塞 Redis 的主进程
-
当子进程完成了 RDB 文件的创建后,会发送信号给主进程,与此同时主进程会通过轮询来接收子进程的信号
-
-
-
我们可以通过 lastsave 指令来查看同步操作是否成功
-
lastsave
- 记录了上一次成功执行 save 或 bgsave 指令的时间
-
-
因此我们可以通过定时任务调用 Redis 的 bgsave 指令去备份 RDB 文件,并按照时间戳存储不同的 RDB 文件,作为 Redis 某段时间的全量数据备份
四、bgsave 原理
-
在执行了 bgsave 指令后,Redis 会先去检查当前主进程是否存在正在执行的 AOF / RDB 子进程,如果存在,则返回错误,这是为了防止子进程之间的相互竞争 (即在执行 bgsave 期间,客户端再次发送 save 或 bgsave 指令时,会被 Redis 拒绝执行);如果不存在,则会触发持久化,此时会调用 Redis 源码中的 rdbSaveBackground 方法,执行 fork 系统调用,创建一个子进程来完成数据备份操作
-
fork 指令是用来创建子进程的,在 Linux 下 fork 系统调用实现了Copy-on-Write (写时复制)
-
在传统方式下,父进程在创建子进程时,会把所有资源都复制给子进程,这种方式实现简单,但效率低下,可能存在复制的资源对于子进程毫无作用的情况
-
在 Linux 下,为了降低创建子进程的成本,改进了 fork 的实现方式:当父进程创建子进程时,内核为子进程创建了虚拟空间,父子两个进程使用相同的物理空间,只有当父子进程发生更改时,才会为子进程分配单独的物理空间,这种改进方式即为写时复制
-
-
什么是 Copy-on-Write (COW,写时复制)?
-
如果有多个调用者同时请求相同资源 (如内存或磁盘上存储的数据),它们会获取相同的指针来指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本给该调用者,而其他调用者所见到的资源仍保持不变
-
此做法的优点在于:如果调用者没有修改该资源,就不会有副本被创建,因此多个调用者只是进行读取操作时,可以共享同一份资源
-
在 COW 的处理过程中,需要维持一个为读请求使用的指针,并在新数据写入完成后更新这个指针,以提升读写并发能力,因此 COW 也间接地提供了数据更新过程中的原子性,在保证数据完成性的同时,还保证了一定的读写效率
-
五、自动触发 RDB 持久化的方式
-
根据配置文件中的
save m n
指令定时触发 (用的 bgsave) -
主从复制时,主节点会自动触发
-
执行 Debug Reload 时会自动触发
-
执行 Shutdown 且没有开启 AOF 持久化时会自动触发