项目 GitHub 地址:github/booklet Redis 提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting,RDB),它可以将存在于某一时刻的所有数据都写入硬盘里面。 另一种方法叫只追加文件(append-only file,AOF),它会在执行写命令时,将被执行的写 ..

Redis 在 Docker 中的数据持久化

项目 GitHub 地址:github/booklet

Redis 提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting,RDB),它可以将存在于某一时刻的所有数据都写入硬盘里面。

另一种方法叫只追加文件(append-only file,AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。

这篇文章梳理了 Redis 两种持久化方法的知识点,并通过 Docker + Docker-Compose 进行环境的模拟,来进行数据的备份与恢复等操作。

至于测试数据,我通过一个 python 脚本批量录入三百万条 key-value 键值对(会消耗 719.42M 内存,来源于 redis-cli info 信息),没有 python 环境的同学,可以使用我在项目里准备的另一个 shell 脚本

python 脚本代码:

# -*- coding: UTF-8 -*-
# file write.py
# author liumapp 
# github https://github.com/liumapp
# email liumapp.com@gmail.com
# homepage http://www.liumapp.com 
# date 2019/9/9
#
import redis

r = redis.Redis(host="127.0.0.1", port=6379, db=0, password="admin123")
print("开始插入三百万条数据,每10万条数据提交一次批处理")
with r.pipeline(transaction=True) as p:
    value = 0
    while value < 3000000:
        print("开始插入" + str(value) + "条数据")
        p.sadd("key" + str(value), "value" + str(value))
        value += 1
        if (value % 100000) == 0:
            p.execute()

RDB

RDB 持久化是通过创建快照来获得数据副本,即简单粗暴的直接保存键值对数据内容

要启用 RDB(并关闭 AOF),我们需要修改 Redis 的配置文件(./redis_config/redis.conf):

requirepass admin123

save 60 1000
stop-writes-on-bgsave-error no
rdbcompression no
dbfilename dump.rdb

appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

dir /data/

上述配置会通过 docker-compose 的配置,映射到 Redis 容器中并启用,具体在下面的实操中介绍

RDB 配置说明

上述配置中与 RDB 相关的配置如下

RDB 触发条件

RDB 的触发条件会比 AOF 麻烦,大致可以分为以下几种:

RDB-Docker 实操

AOF

AOF 持久化会将被执行的写命令写到 AOF 文件的末尾,以此来记录数据发生的变化。因此,Redis 只要从头到尾重新执行一次 AOF 文件包含的所有写命令,就可以恢复 AOF 文件所记录的数据集。

要启用 AOF(并关闭 RDB),我们需要修改 Redis 的配置文件(./redis_config/redis.conf)

requirepass admin123

#save 60 1000
stop-writes-on-bgsave-error no
rdbcompression no
dbfilename dump.rdb

appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

dir /data/

上述配置会通过 docker-compose 的配置,映射到 Redis 容器中并启用,具体在下面的实操中介绍

AOF 配置说明

上述配置中与 AOF 相关的配置如下

AOF 触发条件

直接根据 appendfsync 的设置进行触发

AOF 重写机制

在上面的配置中,已经通过 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 两个参数,简单介绍了 Redis 的 BGREWRITEAOF 重写命令

那么,为什么要用 AOF 重写机制呢?

因为 AOF 持久化是通过保存被执行的写命令来记录 Redis 数据库状态的,所以 AOF 文件随着时系统运行会越来越大

而过于庞大的 AOF 文件会产生以下不良影响

所以 Redis 提供了一套 AOF 重写机制,通过创建一个新的 AOF 文件来替换掉旧的 AOF 文件,这两个文件所保存的数据状态是相同的,但新的 AOF 文件不会包含冗余命令,所以体积会较旧 AOF 文件小很多

但在实际的使用中,我们需要非常小心,不能让 Redis 的重写命令执行的过于频繁 (注意:auto-aof-rewrite-percentage 的单位是百分比,值越大,重写频率越低,也千万别出现 0 这种值) 因为 BGREWRITEAOF 的工作原理和 BGSAVE 创建快照的工作原理非常相似:Redis 会创建一个子进程,然后由子进程负责对 AOF 文件进行重写,因为 AOF 文件重写也需要用到子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在 AOF 持久化中也同样存在

更具体的 AOF 重写工作原理:

BGREWRITEAOF 的工作流程图如下所示**(绘图源代码在项目的./articles/bgrewriteaof.puml 文件下)**:

bgrewriteaof.png

AOF-Docker 实操

总结

RDB 跟 AOF 都可以确保 Redis 的数据持久化,但各有特点

RDB 因为有默认的指令 SAVE 跟 BGSAVE 支持,所以比较适合对数据库做全量备份,比如每天凌晨 3 点开始执行一次 BGSAVE

而 AOF 因为是保存的写命令,因而更适合实时备份,事实上现在企业应用也基本都是采用的 AOF

但光是使用了 RDB 或 AOF、甚至两个一起用,也还是不够的

对于一个需要支持可扩展的分布式平台而言,我们还需要提供一套复制备份机制,允许在一个周期内,自动将 AOF 或者 RDB 的文件备份到不同的服务器下

这种情况下,我们就需要使用 Redis 的复制并生成数据副本功能,具体内容我会在下一篇文章进行实操记录

参考链接

  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    143 引用 • 209 回帖 • 803 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架或包括系统。

    225 引用 • 412 回帖 • 627 关注
回帖   
请输入回帖内容...