Redis(5) Redis持久化操作超详细讲解!!

redis是内存数据库,所有的数据都会默认存在内存中,如果不进行持久化操作,当出现断电等问题,数据都不会保存

一、RDB

是指在时间间隔内将内存中的数据集快照写入磁盘。Redis会单独创建一个子进程来进行持久化,会先将数据写入一个临时文件中,待持久化都结束了,再用这个临时文件替换上一次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模的数据恢复,且对于恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加高效,RDB的缺点是最后一次持久化后的数据可能会丢失。在redis启动的时候会自动将rdb文件的数据读到内存中。

RDB触发保存的两种方式

1、自动触发

进入配置文件中将sava注释打开  

 首先 在默认配置下我们很难演示这个过程,所以需要对它进行修改

 新增了一条配置,在10秒内执行两次即可实现写入操作,修改完配置之后重启redis进行测试

现在data目录下是没有文件的

在10秒内输入三条命令

会将数据写入dump.rdb文件中

每次触发保存只会保存两条,根据save的条件进行保存。

-----------------------------------------------------------------------------------------------------------------------------

  • stop-writes-on-bgsave-error :默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了
  • rdbcompression ;默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。
  • rdbchecksum :默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
  • dbfilename :设置快照的文件名,默认是 dump.rdb
  • dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。
  • 也就是说通过在配置文件中配置的 save 方式,当实际操作满足该配置形式时就会进行 RDB 持久化,将当前的内存快照保存在 dir 配置的目录中,文件名由配置的 dbfilename 决定。

2、手动触发

①、save
        该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。
        显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。
②、bgsave

        执行bgsave命令的时候,redis会自己fork出一条子进程,由这条子进程去执行,这样就不会影响到客户端对于redis 的正常操作 有意思的是,我们都知道,进程与进程之间的内存不是共享的,那么子进程是如何获取到主进程的内存数据呢?
真像是在主进程fork子进程的同时,会把自己内存中的数据同时复制一份给子进程,这样就相当于子进程可以读取到主进程的数据了,然后子进程就可以愉快的进行io操作了.(将内存中的数据写入磁盘中).有的小伙伴可能会问,那么这个复制内存的操作是立即执行的吗,其实并不是的,正常情况下redis的服务大部分都是读操作,在fork子进程的时候,子进程其实并没有直接复制一份主进程的数据,而是给他分配了一个虚拟的内存地址,指向了父进程的内存地址,知道父进程的内存数据发生改变的时候才会进行复制内存的操作. 又有一个问题来了,如果在fork期间客户端又发起了新的操作,redis会怎样做呢,答案相信大家都猜到了,当然是等着了,毕竟redis是单线程的,fork这个过程结束后,redis的子进程就会进行持久化操作了,所以redis主进程理所应当的就创建了一份新的rdb文件,直到子进程完成持久化操作后,才会删除掉之前的rdb文件,以这份新的rdb文件代替. 所以大家也发现了,fork的时间长短其实是跟当时redis中的数据量有很大关系的,在其他条件恒定的情况下,随着数据量的增大,redis 的fork操作时间也会变长.为了性能,基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令,也就是自动提交。

写时复制:

kernel把父进程中所有的内存页的权限都设为read-only,然后子进程的地址空间指向父进程。当父子进程都只读内存时,相安无事。当其中某个进程写内存时,CPU硬件检测到内存页是read-only的,于是触发页异常中断(page-fault),陷入kernel的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份。

rdb就是采用了这种机制,避免了双倍内存占用的现象

③、flushall

执行执行 flushall 命令,也会产生dump.rdb文件,但里面是空的,没有意义。

3、优势

适合大规模数据恢复

对数据完整性和一致性要求不高更适合使用

节省磁盘空间(rdb文件一般来说都会比aof文件要小很多)

数据恢复块

4、劣势

数据不完整性

在fork子进程的时候需要消耗两倍的内存。

二、AOF

以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有指令记录下(读操作不记录),只需追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从头到尾执行一次以完成数据恢复工作。

AOF持久化流程:

1、客户端的请求写命令会被append追加到AOF缓冲区;

2、AOF缓冲区根据AOF持久化策略【always,everysec,no】将操作sync同步到磁盘的AOF文件中;

3、AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF容量;

4、redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的

1、开启AOP

在Redis中AOF是默认不开启的需要我们手动开启

 搜索appendonly找到该位置

 

将no改成yes

 重启redis即可看到aof文件

要点: 当AOF和RDB同时开启的时候,系统默认读取AOF的数据(数据不会丢失),所以之前如果用的是rdb持久化数据再转成AOF,那么就读取不到之前的数据。

打开了之后每执行一指令就会自动持久化

2、异常恢复

当AOF文件出现异常的时候,redis的客户端时不能正常连接的,这时候需要我们修复文件

现在先模拟一下异常情况:

①、先存入几条数据

②、打开编辑aof文件

在里面加入自定义字符串让文件出错

然后重启一下redis,重新启动redis客户端,会发现已经不能连接了

 ③、解决方案

 容器启动不起来,我们不能进入容器中的/usr/local/bin/找到redis-check-aof。但是有其他的方法

输入 :

docker inspect 容器id  

Ⅰ、先找到备份的aop叫什么名字(以防不是默认文件名的情况)

找到了data,就是我们存放aof文件的位置,而source就是宿主机数据卷的位置,复制一下source的路径进入其中

可以看到aof文件,这里我用的是默认名字

Ⅱ、找到修复文件工具(redis-check-aof)

我们知晓这个工具的具体名字 可以直接通过find命令找到

find --name “文件名”  

 找到文件后直接执行

找到的文件名加上 --fix  后面跟着aof文件的路径执行即可

3、AOF的同步频率设置

 1、appendfsync always  

始终同步,每次Redis的写入都会立刻计入日志;性能较差但数据完整性较好。

2、appendfsync everysec

每秒同步,每秒计入日志一次,如果宕机,本秒的数据可能会丢失

3、appendfsync no

redis不主动进行同步,把同步时机交给操作系统

4、ReWrite压缩

Aof采用文件追加方式,文件会越来越大,为了避免出现这种情况,新增了重写机制,当AOF文件大小超过所设定的阈值时,Redis就会启用AOF文件的内容压缩,只保留可以恢复的数据的最小指令集,也可以使用bgrewriteaof手动压缩

如何实现?

AOF文件持续增长时,会fork出一条新进程来将文件重写(也就是先写入临时文件,最后再rename),而父进程继续接受命令,现在的写操作命令都会被额外添加到一个aof_rewrite_buf_blocks缓冲中当子进程rewrite结束后,父进程收到子进程退出信号,把aof_rewrite_buf_blocks的缓冲添加到rewrite后的文件中,然后切换AOF的文件fd。

重写策略?

 如上图所示,上图配置的大体意思为当AOF文件大小超过了64m并且超过了64m的100%(128m)就开始重写。

auto-aof-rewrite-percentage 100   这行配置设置倍率

auto-aof-rewrite-min-size 64mb   这行配置设置底数

总体为当文件大小超过底数的倍率倍时,就自动重写

appendfsync-on-rewrite

同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?在linux的操作系统的默认设置下,最多会丢失30s的数据

5、优势

备份机制更加稳健,丢失数据概率更低

可读的日志文本,通过操作AOF稳健,可以处理错误操作

6、劣势

比起rdb更占用磁盘(除了要记录数据,还记录了指令)

恢复备份速度更慢

每次读写都同步的话,有一定的性能压力

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值