/首页
/开源
/关于
我所认知的redis(二)--- 持久篇
发表@2018-09-13 09:15:21
更新@2023-01-21 22:47:40
redis中的数据都是存储在内存中的,所以对于数据的持久化是绕不开的话题。 redis的持久化有两种方案,一是RDB,二是AOF。其中前者大概意思就是将内存数据全部快照然后存储到硬盘上,后者则是类似于mysql的二进制日志方案。 这次我打算结合redis的配置文件来分别记录一下两种备份方式。 - RDB,会定时触发然后将redis存储在内存中的数据以快照的方式全量持久化到硬盘上。在redis-cli控制台下输入命令save就可以实时触发这个操作,此时redis将会被阻塞,不会再响应客户端的其余任何请求,所以为了避免这种被阻塞,可以用bgsave来触发rdb备份。这两个区别就是bgsave以后redis的主进程会fork出一个子进程来做快照持久化,而主进程可以继续相应客户端的任何请求。默认情况下,redis是fork出一个子进程来完成的快照持久化。那么,redis自己何时会触发持久化呢?看下redis中关于rdb所有配置项: ```php // 默认情况下从redis.conf文件的第196行开始 // save 秒数 发生变化的key的数量。所以下面三行的意思就是60秒内如果至少10000个key发生了改变、300秒内至少10个key发生了改变、900秒内至少1一个key发生了改变,那么就会触发bgsave save 900 1 save 300 10 save 60 10000 // 如果bgsave遇到错误时停止写入 stop-writes-on-bgsave-error yes [ 另一个选项自然就是no了 ] // 开启rdb文件压缩,可以有效减少rdb文件的体积。开启压缩需要付出的代价自然就是cpu点数了,如果你为了节省cpu资源,可以关闭压缩 rdbcompression yes // 开启crc64校验可以让rdb文件具备更好的完整性,但是也是需要cpu点数的,可以选择关闭 rdbchecksum yes // rdb文件的名字 dbfilename dump.rdb // redis的工作目录,上面的rdb文件就会保存在redis的工作目录中 dir /var/lib/redis ``` 所以 - AOF,全称是Append Only File,翻译过来大概就是 “ 只可追加的文件 ”,其实这种方式跟mysql中的binlog很类似,aof文件中记录都是在redis中执行过的命令,比如set user:1 jim、set user:2 tom两条命令会被记录下来,它并不记录数据本身,这个时候大家可能会看出问题来就是:假如我连续set了10000次,但是最后这10000个key我又全部删除了,aof文件岂不是会记录20000条命令?所以为了解决这个问题,针对aof还有个很重要的rewrite机制,从而避免刚才出现那种尴尬境地,记录了20000条命令最终却实际上没有任何数据。将命令追加到aof这个过程redis官方称之为fsync,fsync这个过程是子线程来做的,主线程依然用来处理客户端的请求。下面还是结合配置文件说明aof: ```php // 是否开启aof appendonly no // aof文件名称 appendfilename "appendonly.aof" // fsync时间间隔 appendfsync everysec // 当子进程在对aof文件进行rewrite的时候暂停主进程对fsync的append操作,避免产生冲突。因为aof的时候,是子进程来做的,此时如果主进程来append新的指令了,两个进程同时操作一个文件会产生冲突,所以此时主进程要append的指令会被缓存到内容中,当子进程rewrite完成后会向主进程发送一个信号来通知rewrite已完成,然后主进程再将放到内存中的append指令追加到aof文件尾部 no-appendfsync-on-rewrite no // 触发aof文件rewrite的条件 // 当当前aof文件大小超过上次aof文件体积100%后,才会启动rewrite auto-aof-rewrite-percentage 100 // 开启rewrite的aof文件最小体积,也就说只有当aof文件超过了64mb后,才会可能产生rewrite。用程序语言表达就是 只有当aof文件体积大于64mb并且当前aof文件体积比上次变化超过了100% 才会产生rewrite。如果aof文件体积小于64mb,那么即便文件变化率超过了100%,也不会发生rewrite。 auto-aof-rewrie-min-size 64mb // 忽略aof文件中错误的不完整的日志,如果该选项为no,那么redis会加载aof失败。损坏的aof文件可以尝试用redis-check-aof来修复 aof-load-truncated yes // 这是redis 4.0出现的新特性,集成了rdb和aof的优点的一个产物。大家知道在aof rewrite的时候还是要全量读取一次所有的数据,然后rewrite期间缓存下的命令。既然都要全量读取一次了,为何不在这次全量读取的时候就索性以rdb格式写入到文件呢?然后再追加rewrite期间产生的新aof指令。这样,数据不仅恢复快,还能保证数据完整性。默认情况下,该选项处于关闭状态。 aof-user-rdb-preamble no ``` TIPS: - rdb恢复速度快,aof恢复速度相对要慢一些。 - 如果aof开启了,那么redis在启动时会选择根据aof文件恢复数据而不是rdb,所以一定要保存好rdb文件。 - rdb和aof可以同时开启,最大可能地保证数据完整性。如果redis中的数据都是缓存类数据,可以考虑只选择一样即可。 - 检测修复rdb文件的工具叫做redis-check-rdb,检测修复aof文件的工具叫做redis-check-aof。 - 如果你有1G的redis数据,那么理论上讲做一次bgsave操作最大需要2G内存,但实际上得益于Copy-On-Write(写时拷贝,COW机制),并不一定会需要2G内存,只有在当主进程将所有的key全部修改过的情况下,才会需要2G内存。 - 建议redis内存使用量在30%-50%之间,超过50%这个限制就要留心注意下了。