前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis持久化详解

Redis持久化详解

作者头像
dogfei
发布2020-07-31 14:33:00
4880
发布2020-07-31 14:33:00
举报
文章被收录于专栏:devops探索

持久化

先看下redis的工作流程

1、写操作

  • 客户端向服务端发送写操作(数据在客户端的内存中)
  • 数据库服务端接收到写请求的数据(数据在服务端的内存中)
  • 服务端调用write(2)这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)
  • 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)
  • 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)

可知只有当第五步完成以后数据才会写到磁盘上。

2、持久化介绍

持久化:将数据放到断电后数据不会丢失的设备中,也就是我们通常理解的硬盘上。

持久化操作分为两种形式

  • RDB   RDB持久化可以在指定时间间隔内生成数据集的时间点快照
  • AOF   AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据

3、详细介绍

RDB优点:

  • RDB是一个非常紧凑的文件,它保存了redis在某个时间点上的数据集,这种文件非常适合用于备份,灾难恢复
  • RDB可以最大化redis的性能,父进程在保存RDB文件时唯一要做的就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无需执行任何磁盘I/O操作
  • RDB在恢复大数据集时速度比AOF要快

RDB缺点:

  • RDB有可能造成数据丢失,因为RDB通过设置不同的保存点来控制保存RDB文件的频率,假如现在是5分钟保存一次RDB文件,在这期间如果发生故障,可能会丢失好几分钟的数据
  • 每次RDB时,redis都要fork出一个子进程,并由子进程来进行实际的持久化工作,在数据集比较庞大时,fork()会比较耗时,造成服务器在某个时间段内停止处理客户端,如果这时cpu不够,可能这种停止会长达一秒

RDB保存数据过程:

  • redis调用fork()子进程,同时拥有父进程和子进程
  • 子进程将数据集写入到一个临时RDB文件中
  • 当子进程完成对新RDB文件的写入时,redis用新RDB文件替换原来的RDB文件,并删除旧的RDB文件

AOF优点:

  • AOF持久化默认是每秒钟fsync一次,在这种配置下,redis仍然可以保持良好的性能,并且就算发生故障停机,最多只会丢失一秒钟的数据
  • AOF文件是一个只进行追加操作的日志文件,因此对AOF文件的写入不需要进行seek,即使日志因为某些原因而包含了未写入完整的命令,redis-check-aof工具也可以轻易修复这种问题
  • redis可以在AOF文件体积变得过大时,自动的在后台对AOF进行重写,重写后的AOF文件包含了恢复当前数据集所需的最小命令集合,整个重写操作也是绝对安全,因为在重写过程中,会继续将命令追加到现有的AOF文件里,及时发生故障,也不会丢失数据
  • AOF文件有序的保存了对数据库执行的所有写入操作,这些写入操作以redis协议格式保存

AOF缺点:

  • AOF文件体积大于RDB
  • 所使用的fsync策略,使得AOF的速度可能会慢于RDB,在一般情况下,每秒fsync的性能依然非常高,而关闭fsync可以让AOF的速度和RDB一样快,即使在高负荷之下
  • AOF在过去曾经发生过Bug:因为个别命令的原因,导致AOF文件在重新载入时,无法将数据集恢复成保存时的原样

AOF持久化过程:

  • redis执行fork(),现在同时拥有父进程和子进程
  • 子进程开始将新AOF文件的内容写入到临时文件
  • 对于所有新执行的写入命令,父进程一边将他们累积到一个内存缓存中,一边将这些改动追加到现有AOF文件的末尾,这样即使在重写的中途发生停机,现有的AOF文件也还是安全的
  • 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新AOF文件的末尾
  • 现在redis用新文件替换旧文件,之后所有命令都会直接追加到新AOF文件的末尾

4、如何配置

开启RDB,关闭AOF:

1 2 3 4 5 6 7 8 9 10 11

save 900 1 save 300 10 save 60 10000 rdbcompression no #默认Redis会采用LZF对数据进行压缩。如果你想节省点CPU的性能,你可以把压缩功能禁用掉,但是数据集就会比没压缩的时候要大 rdbchecksum no #数据校验,从版本5的RDB的开始,一个CRC64的校验码会放在文件的末尾。这样更能保证文件的完整性,但是在保存或者加载文件时会损失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,这样文件在写入校验码时会用0替代,加载的时候看到0就会直接跳过校验 dbfilename redis.rdb dir /home/backup/redis stop-writes-on-bgsave-error yes #错误处理,如果redis在后台生成快照时失败,就会停止接收数据,目的是告诉你没有持久化成功 appendonly no

开启AOF,关闭RDB:

1 2 3 4 5 6 7 8

appendonly yes appendfilename redis.aof # appendfsync always appendfsync everysec # appendfsync no no-appendfsync-on-rewrite no auto-aof-rewrite-min-size 64mb

开启RDB和AOF:

1 2 3 4 5 6 7 8 9 10 11 12

save 900 1 save 300 10 save 60 10000 appendonly yes appendfilename zhoujy.aof # appendfsync always appendfsync everysec # appendfsync no no-appendfsync-on-rewrite no auto-aof-rewrite-min-size 64mb

5、其他配置

手动生成快照:

  • save   使用同步的方式生成RDB快照文件,这意味着在这个过程中会阻塞所有其他客户端的请求。因此不建议在生产环境使用这个命令,除非因为某种原因需要去阻止Redis使用子进程进行后台生成快照(例如调用fork(2)出错)
  • bgsave  使用后台的方式保存RDB文件,调用此命令后,会立刻返回OK返回码。Redis会产生一个子进程进行处理并立刻恢复对客户端的服务。在客户端我们可以使用LASTSAVE命令查看操作是否成功

日志重写:

随着写操作的不断增加,AOF文件会越来越大。例如你递增一个计数器100次,那么最终结果就是数据集里的计数器的值为最终的递增结果,但是AOF文件里却会把这100次操作完整的记录下来。而事实上要恢复这个记录,只需要1个命令就行了,也就是说AOF文件里那100条命令其实可以精简为1条。所以Redis支持这样一个功能:在不中断服务的情况下在后台重建AOF文件。

工作原理如下:

  • Redis调用fork(),产生一个子进程。
  • 子进程把新的AOF写到一个临时文件里。
  • 主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全。
  • 当子进程完成文件的重写后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新AOF里。

1 2 3 4 5 6 7 8 9 10

#在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。 #设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes no-appendfsync-on-rewrite yes # Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。 # 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。 # 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。 auto-aof-rewrite-percentage 100 #设置为0表示禁用日志重写功能 auto-aof-rewrite-min-size 64mb

数据损坏修复:

如果因为某些原因导致AOF文件损坏,导致redis加载不了,可以使用如下方式修复:

1 2

先进到redis的/bin目录,然后执行: redis-check-aof --fix

RDB切换到AOF:

如果要更换持久化的方式,由RDB更换成AOF,我们需要做如下操作:

  • 备份RDB文件

redis-cli config set appendonly yes redis-cli config set save "”

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

* 验证数据是否一致 这种方式的切换在redis重启后就失效了,需要修改配置文件 还有另外一种情况,就是现在公司的线上环境,现在使用的是RDB的方式,但是由于,系统每隔五分钟左右的时间,负载和cpu和内存都会抖动一下,持续时间大概几秒钟,所以这里我们想更换一下持久化方式,有两种方法实现: 1. 开启AOF之前,先执行bgrewriteaof操作,然后重启 ``` redis 127.0.0.1:6379> keys * #查看是否有数据 (empty list or set) redis 127.0.0.1:6379> set name ttd OK redis 127.0.0.1:6379> keys * 1) "name" redis 127.0.0.1:6379> bgsave #保存数据 Background saving started redis 127.0.0.1:6379> keys * 1) "name" #只有一个RDB文件,没有AOF文件 redis 127.0.0.1:6379> bgrewriteaof #执行合并重写功能,生成AOF文件 Background append only file rewriting started #这时候去打开redis.conf 文件中的aof参数(appendonly yes),重启生效。 #日志里面出现:* DB loaded from append only file: 0.000 seconds redis 127.0.0.1:6379> keys * #数据还在 1) "name"

  1. 利用CONFIG GET/SET 的方法动态修改配置文件 ``` redis 127.0.0.1:6379> BGSAVE Background saving started #此时,只有rdb文件

#动态修改参数,把aof功能开启:appendonly yes redis 127.0.0.1:6379> CONFIG SET appendonly yes #动态修改参数 OK redis 127.0.0.1:6379> CONFIG GET append*

  1. “appendonly”
  2. “yes”
  3. “appendfsync”
  4. “everysec” redis 127.0.0.1:6379>

#aof文件已经生成,并且有数据(同步rdb)

#日志里面的信息:* Background append only file rewriting started by pid 3165 #因为参数是动态修改的,在重启之后会失效,所以在维护的时候修改redis.conf文件的参数即可

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

</li> </ol> #### AOF持久化造成文件体积过大 我们可以通过执行bgrewriteaof命令来对redis的aof进行重写,即重建一个新的AOF文件来替代现有的AOF文件,新旧文件所保存的数据库状态相同,但新AOF文件不会包含任何冗余命令,所以体积会比旧的小很多。 AOF重写实现原理: 首先从数据库读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,但会产生一个问题,重写会进行大量的写入操作,阻塞服务器线程,无法处理新的命令请求,所以这时需要将AOF重写放到子进程里执行,这样父进程便可以正常工作,但这时又产生了一个新的问题,子进程在进行AOF重写期间,服务器进程还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而产生数据库状态不一致,所以redis设置了一个AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当服务器执行完一个写命令之后,它会将这个写命令发送给AOF重写缓冲区,当子进程完成AOF重写工作之后,会向父进程发送一个信号,父进程在接到该信号之后,会调用信号处理处理函数,执行一下工作: 1. 将AOF重写缓冲区中的所有内容写入到新AOF文件中,这时新的AOF文件与当前的数据库状态一致 2. 对新的AOF文件进行改名,覆盖现有的AOF文件,完成新旧两个AOF文件的替换 在整个重写过程中,只有信号处理函数执行时会对服务器造成阻塞。 原理图: ![][1] 看下示例: 执行重写命令 ``` 9998> BGREWRITEAOF Background append only file rewriting started

代码语言:javascript
复制
查看AOF文件变化

```

[root@xs_82_208 /data/redis]# ll -rw-r–r– 1 redis redis 1600484096 Feb 28 09:31 appendonly.aof -rw-r–r– 1 redis redis 537021850 Feb 28 09:31 temp-rewriteaof-3563.aof

1 2 3 4 5 6

重写过程中会把新的操作写入缓冲区,重写完成后会把新的AOF文件覆盖旧的文件 ``` [root@xs_82_208 /data/redis]# ll -rw-r--r-- 1 redis redis 845349884 Feb 28 09:36 appendonly.aof

代码语言:javascript
复制
重写过程中,cpu和内存会有短暂的飙升,过后便会恢复正常
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 持久化
    • 1、写操作
      • 2、持久化介绍
        • 3、详细介绍
          • 4、如何配置
            • 5、其他配置
            相关产品与服务
            云数据库 Redis
            腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档