上一篇文章,我们讲的是 Redis 的一种基于内存快照的持久化存储策略 RDB,本质上他就是让 redis fork 出一个子进程遍历我们所有数据库中的字典,进行磁盘文件的写入。

但其实这种方式是有缺点的,先不说阻塞式 save 调用会阻塞整个 redis 服务,即便异步式 bgsave 也是基于时间间隔,每多少秒触发了多少次更新操作才会生成 RDB 文件,那么如果某次 RDB 生成之后,紧接着服务宕机,就至少丢失几秒甚至更多的数据,并且这些数据是无法挽回的。

而 AOF 是 redis 中的另一种数据持久化策略,它基于操作日志,也是一个很优秀的持久化策略,当然也有缺点。那么本篇就来讲讲这个 AOF 持久化策略。

一、什么是 AOF 持久化策略

AOF 即 append only file,当 redis 采用这这种数据持久化策略的时候,每当 redis 服务器收到一条更新命令时,操作结束之后会将这条命令添加到 aof 内存缓冲区,特定的时间下刷新缓冲区到磁盘文件中,也就是我们的 aof 文件。

默认的 redis 启动配置文件中,会有这么两条配置:

appendonly 指定 redis 是否启用 AOF 持久化策略,appendfilename 指明生成的 AOF 文件名称。

你也可以将 appendonly 选项指定为 yes,然后执行一条 set 命令,看看 redis 根目录下有没有生成一个 appendonly.aof 文件。

redis.conf 中还有 appendfsync 这么一条配置,它指明 AOF 文件的写入频率,即便 linux 中文件 IO 使用的高效的 epoll,但每收到一条更新命令就进行一次文件 IO,未免也太低效,况且也没必要。

appendfsync 的配置项有以下三种值可选:

  • always:每一次系统 serverCorn 函数调用就刷新一次缓存区
  • everysec:每秒执行一次磁盘写入,期间所有的命令都会存储在 aof 缓存区
  • no:不做控制,任由操作系统决定什么时候刷新缓冲区

redis 默认配置是 everysec,即每秒刷新一次缓存区。

二、AOF 重写

所以,理论上来说,随着 redis 服务器运行时间的持续,生成的 aof 文件只会越来越大,redis 提供 AOF 重写策略帮助优化和压缩 aof 文件。

比如:

set a "a"
set b "b"
set c "c"
del a
del b

正常情况下,aof 文件中会保存着五条命令的 log,然后数据恢复的时候依次执行即可。而当你启动 AOF 重写后,实际上我们的 aof 文件中只有 set c "c" 这一条命令的 log。

以上只是一个简单的示例,实际上 AOF 重写达到的效率比这优秀的多的多,往往能将几百条甚至几千条的命令日志,重写优化成个位数。带给我们最直观的好处就是,aof 文件体积变小,数据恢复速度变快。

一般来说,我们可以通过向 redis 服务器发送 bgrewriteaof 命令触发服务器对 aof 文件进行重写,如果当前有正在运行的重写子进程,则本次重写 会推迟执行,否则,直接触发一次重写。

除此之外,我们还可以在配置文件中配置 aof 文件达到多大,自动触发文件重写。

因为 aof 文件重写一样是 fork 子进程并由子进程处理的,主进程依然提供服务,所以 redis 还提供一块重写缓冲区,当发现有子进程正在进行 aof 文件重写,最新的请求命令除了会添加到 AOF 缓冲区,还会添加进 AOF 重写缓冲区,当子进程完成重写任务后,主进程阻塞式将重写缓冲区的命令日志添加进最新的 aof 文件中。

看几条配置

no-appendfsync-on-rewrite 配置了当 redis 服务器因为某些情况即将阻塞(例如 save)时是否需要将缓冲区中的 aof 命令写入到磁盘,配置 yes 则每次遇到阻塞操作时刷新缓存到磁盘,配置为 no 则无需关心服务器阻不阻塞,缓存命令在缓存区。

auto-aof-rewrite-percentage 配置了当 aof 文件相较于上一版本的 aof 文件大小的百分比达到多少时触发 AOF 重写。举个例子,auto-aof-rewrite-percentage 选项配置为 100,上一版本的 aof 文件大小为 100M,那么当我们的 aof 文件达到 200M 的时候,触发 AOF 重写。

auto-aof-rewite-min-size 配置了最小能容忍 aof 文件大小,超过这个大小必须进行 AOF 重写。

三、RDB 与 AOF

RDB 基于内存快照,有两种方式 save 和 bgsave,前者会阻塞 redis 服务,后者是异步 fork 子进程不影响主进程提供服务。大部分情况,我们会通过配置时间间隔触发 RDB 文件写入。RDB 文件中保存的是 redis 内存中所有的数据一份快照。

优点是:

  1. 相同的数据量下,rdb 文件要小于 aof 文件,且恢复速度要快于 aof
  2. rdb 文件中是整个数据的完整备份快照,数据存储紧凑即便不同版本的 redis,也能顺利恢复
  3. 整个 rdb 持久化,只需要 fork 一个子进程进行持久化即可,父进程依然可以提供服务,效率最大化

缺点是:

  1. 容易丢失数据,即便配置了事件时间触发备份,也至少丢失一秒数据
  2. 如果数据量太大,fork 子进程的时候会阻塞毫秒级别时间

AOF 是基于命令操作日志,每条更新命令都会被刷到缓存区,然后在特定的时间节点被写入 aof 磁盘文件。

优点是:

  1. 相较于 RDB,AOF 数据可靠性更强,最多丢失一秒数据
  2. 数据库容错率变好,一些误操作可以通过直接改 aof 文件进行回退

缺点是:

  1. AOF 文件通常较大且恢复效率比不上 RDB,不适合做数据冷备份

总的来说,AOF 策略会使数据稳定性更高,具有更完整的数据备份,RDB 恢复效率高适合做灾难恢复,建议生产环境上两者都开启。

ps:Redis 官方号称后续出一个新的持久化策略,整合 RDB 和 AOF 提供更高效率的数据持久化,期待中。

Redis 中的数据持久化策略(AOF)的更多相关文章

  1. Redis 中的数据持久化策略(RDB)

    Redis 是一个内存数据库,所有的数据都直接保存在内存中,那么,一旦 Redis 进程异常退出,或服务器本身异常宕机,我们存储在 Redis 中的数据就凭空消失,再也找不到了. Redis 作为一个 ...

  2. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  3. Redis进阶:数据持久化,安全,在PHP中使用

    一.redis数据持久化 由于redis是一个内存数据库,如果系统遇到致命问题需要关机或重启,内存中的数据就会丢失,这是生产环境所不能允许的.所以redis提供了数据持久化的能力. redis提供了两 ...

  4. 读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots

    读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots   以下为异常详细信息: Exception in thread &q ...

  5. 动手实现 LRU 算法,以及 Caffeine 和 Redis 中的缓存淘汰策略

    我是风筝,公众号「古时的风筝」. 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. 那天我在 LeetCode 上刷到一道 LRU 缓存机制的问题, ...

  6. Redis 中的过期删除策略和内存淘汰机制

    Redis 中 key 的过期删除策略 前言 Redis 中 key 的过期删除策略 1.定时删除 2.惰性删除 3.定期删除 Redis 中过期删除策略 从库是否会脏读主库创建的过期键 内存淘汰机制 ...

  7. iOS中的数据持久化方式

    iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data. 1.属性列表 涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults ...

  8. IOS学习:ios中的数据持久化初级(文件、xml、json、sqlite、CoreData)

    IOS学习:ios中的数据持久化初级(文件.xml.json.sqlite.CoreData) 分类: ios开发学习2013-05-30 10:03 2316人阅读 评论(2) 收藏 举报 iOSX ...

  9. Android中的数据持久化机制

    Android中几种最简单但是却最通用的数据持久化技术:SharedPreference.实例状态Bundle和本地文件. Android的非确定性Activity和应用程序生存期使在会话间保留UI状 ...

随机推荐

  1. python3中map函数

    map函数是Python里面比较重要的函数 map函数后面必须接的是序列(元组/列表/字符串) 在python2中执行一些语句 >>> map(str,[1,2,3,4]) ['1' ...

  2. 微信小程序获取多个input和textarea的值(es6加微信小程序APi)

    wxml js 俩行即可解决,money1,money2,money3

  3. wide&deep模型演化

    推荐系统模型演化 LR-->GBDT+LR FM-->FFM-->GBDT+FM|FFM FTRL-->GBDT+FTRL Wide&DeepModel (Deep l ...

  4. Prometheus + Grafana 部署说明之「安装」

    说明 在前面的Prometheus学习系列文章里,大致介绍说明了Prometheus和Grafana的一些使用,现在开始介绍如何从头开始部署Prometheus+Grafana,来监控各个相关的指标数 ...

  5. Elasticsearch 节点磁盘使用率过高,导致ES集群索引无副本

    目录 一.问题 二.问题的原因 三.问题解决的办法 1. 扩大磁盘 2. 删除部分历史索引 3. 更改es设置 四.扩展 一.问题 最近在查看线上的 es,发现最近2天的索引没有副本,集群的状态也是为 ...

  6. Head First设计模式——组合模式

    最近比较忙,有段时间没有更新设计模式的进度了.今天继续学习组合设计模式. 组合模式的例子我们继续延续上篇<Head First设计模式——迭代器模式>的菜单例子,首先声明下迭代器和组合模式 ...

  7. 小小知识点(三十六)EXCEL闪退解决办法

    1. 首先打开控制面板,从系统和安全中选择管理工具打开Windows事件查看器 2. 点击展开Windows日志-->应用程序.然后在右侧列表中找到出现的错误(点击后,查看下面的信息就知道是不是 ...

  8. 关于javaweb开发的环境搭建(一)Tomcat

    进行Tomcat的下载及环境配置 1.下载地址   http://tomcat.apache.org/ 2.下载的注意事项   下载的Tomcat版本要与自身电脑安装的java版本相匹配,下载时,点击 ...

  9. git版本管理工具(二)

    1.查看历史版本 ·git log ·git reflog 2.版本回退 ·git reset --hard HEAD^(HEAD代表当前版本) ·HEAD^代表回退到上一个版本 以此类推 ·HEAD ...

  10. 详解定时任务中的 cron 表达式

    1.前言 我们经常使用 cron 表达式来定义定时任务的执行策略,今天我们就总结一下 cron 表达式的一些相关知识. 2. cron 表达式的定义 cron 表达式是一个字符串,该字符串由 6 个空 ...