设为首页 加入收藏

TOP

解密Redis持久化(一)
2014-11-24 08:23:59 来源: 作者: 【 】 浏览:6
Tags:解密 Redis 持久化
解密Redis持久化
本文内容来源于 Redis 作者博文,Redis 作者说,他看到的所有针对 Redis 的讨论中,对 Redis持久化的误解是最大的,于是他写了一篇长文来对 Redis 的持久化进行了系统性的论述。文章非常长,也很值得一看,NoSQLFan 将主要内容简述成本文。
  什么是持久化,简单来讲就是将数据放到断电后数据不会丢失的设备中。也就是我们通常理解的硬盘上。 www.2cto.com
  写操作的流程
  首先我们来看一下 数据库在进行写操作时到底做了哪些事,主要有下面五个过程。
客户端向服务端发送写操作(数据在客户端的内存中)
数据库服务端接收到写请求的数据(数据在服务端的内存中)
服务端调用 write (2) 这个 系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)
操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)
磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)
  故障分析
  写操作大致有上面 5 个流程,下面我们结合上面的 5 个流程看一下各种级别的故障。 www.2cto.com
当数据库系统故障时,这时候系统内核还是 OK 的,那么此时只要我们执行完了第 3 步,那么数据就是安全的,因为后续操作系统会来完成后面几步,保证数据最终会落到磁盘上。
当系统断电,这时候上面 5 项中提到的所有缓存都会失效,并且数据库和操作系统都会停止工作。所以只有当数据在完成第 5 步后,机器断电才能保证数据不丢失,在上述四步中的数据都会丢失。
  通过上面 5 步的了解,可能我们会希望搞清下面一些问题:
数据库多长时间调用一次 write (2),将数据写到内核缓冲区
内核多长时间会将系统缓冲区中的数据写到磁盘控制器
磁盘控制器又在什么时候把缓存中的数据写到物理介质上
  对于第一个问题,通常数据库层面会进行全面控制。而对第二个问题,操作系统有其默认的策略,但是我们也可以通过 POSIX API 提供的 fsync 系列命令强制操作系统将数据从内核区写到磁盘控制器上。对于第三个问题,好像数据库已经无法触及,但实际上,大多数情况下磁盘缓存是被设置关闭的。或者是只开启为读缓存,也就是写操作不会进行缓存,直接写到磁盘。建议的做法是仅仅当你的磁盘设备有备用电池时才开启写缓存。
  数据损坏
  所谓数据损坏,就是数据无法恢复,上面我们讲的都是如何保证数据是确实写到磁盘上去,但是写到磁盘上可能并不意味着数据不会损坏。比如我们可能一次写请求会进行两次不同的写操作,当意外发生时,可能会导致一次写操作安全完成,但是另一次还没有进行。如果数据库的数据文件结构组织不合理,可能就会导致数据完全不能恢复的状况出现。
www.2cto.com
  这里通常也有三种策略来组织数据,以防止数据文件损坏到无法恢复的情况:
第一种是最粗糙的处理,就是不通过数据的组织形式保证数据的可恢复性。而是通过配置数据同步备份的方式,在数据文件损坏后通过数据备份来进行恢复。实际上 MongoDB 在不开启 journaling 日志,通过配置 Replica Sets 时就是这种情况。
另一种是在上面基础上添加一个操作日志,每次操作时记一下操作的行为,这样我们可以通过操作日志来进行数据恢复。因为操作日志是顺序追加的方式写的,所以不会出现操作日志也无法恢复的情况。这也类似于 MongoDB 开启了 journaling 日志的情况。
更保险的做法是数据库不进行老数据的修改,只是以追加方式去完成写操作,这样数据本身就是一份日志,这样就永远不会出现数据无法恢复的情况了。实际上 CouchDB 就是此做法的优秀范例。
  RDB 快照
  下面我们说一下 Redis 的第一个持久化策略,RDB 快照。Redis 支持将当前数据的快照存成一个数据文件的持久化机制。而一个持续写入的数据库如何生成快照呢。Redis 借助了 fork 命令的 copy on write 机制。在生成快照时,将当前进程 fork 出一个子进程,然后在子进程中循环所有的数据,将数据写成为 RDB 文件。
  我们可以通过 Redis 的 save 指令来配置 RDB 快照生成的时机,比如你可以配置当 10 分钟以内有 100 次写入就生成快照,也可以配置当 1 小时内有 1000 次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在 Redis 的配置文件中,你也可以通过 Redis 的 CONFIG SET 命令在 Redis 运行时设置规则,不需要重启 Redis。
  Redis 的 RDB 文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的 RDB 文件时,Redis 生成的子进程会先将数据写到一个临时文件中,然后通过原子性 rename 系统调用将临时文件重命名为 RDB 文件,这样在任何时候出现故障,Redis 的 RDB 文件都总是可用的。
  同时,Redis 的 RDB 文件也是 Redis 主从同步内部实现中的一环。
  但是,我们可以很明显的看到,RDB 有他的不足,就是一旦数据库出现问题,那么我们的 RDB 文件中保存的数据并不是全新的,从上次 RDB 文件生成到 Redis 停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用 RDB 的方式进行持久化,因为开启 RDB 的代价并不高。但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB 就无能为力了,所以 Redis 引入了另一个重要的持久化机制:AOF 日志。
  AOF 日志 www.2cto.com
  aof 日志的全称是 append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的 binlog 不同的是,AOF 文件是可识别的纯文本,它的内容就是一个个的 Redis 标准命令。比如我们进行如下实验,使用 Redis2.6 版本,在启动命令参数中设置开启 aof 功能:
./redis-server --appendonly yes
  然后我们执行如下的命令:
redis 127.0.0.1:6379> set key1 HelloOKredis 127.0.0.1:6379> append key1 " World!"(integer) 12redis 127.0.0.1:6379> del key1(integer) 1redis 127.0.0.1:6379> del non_existing_key (integer) 0
  这时我们查看 AOF 日志文件,就会得到如下内容:
$ cat appendonly.aof*2$6SELECT$10*3$3set$4key1$5Hello*3$6append$4key1$7 World!*2$3del$4key1
  可以看到,写操作都生成了一条相应的命令作为日志。其中值得注意的是最后一个 del 命令,它并没有被记录在 AOF 日志中,这是因为 Redis 判断出这个命令不会对当前数据集做出修改。所以不需要记录这个无用的写命令。另外 AOF 日志也不是完全按客户端的请求来生成日
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MongoDB简介 下一篇MongoDB---分片简析

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Redis压力测试实战 - (2025-12-27 09:20:24)
·高并发一上来,微服 (2025-12-27 09:20:21)
·Redis 高可用架构深 (2025-12-27 09:20:18)
·Linux 系统监控 的完 (2025-12-27 08:52:29)
·一口气总结,25 个 L (2025-12-27 08:52:27)