zoukankan      html  css  js  c++  java
  • redis(六)Redis持久化优缺点

    问题 :

    • redis默认的持久化方式
    • 两种方式的优缺点

    概述

    我们知道MySQL中假如按持久化的方式分 : 物理备份 和 逻辑备份 ,前者对应的是 redo log ,后者对应的是 bin log , 也就是说一个记录了某一行的哪个列被修改成了什么值,或是另外一种方式---对某行执行了什么操作(例如:update等),按照这个思路我们就可以很快的理解和把握。

    Redis 分别提供了 RDB 和 AOF 两种持久化机制:

    • RDB 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。
    • AOF 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF文件,以此达到记录数据库状态的目的。

    方式一 : RDB (快照)

    Redis 快照 是最简单的 Redis 持久性模式。当满足特定条件时,它将生成数据集的时间点快照,例如,如果先前的快照是在2分钟前创建的,并且现在已经至少有 100 次新写入,则将创建一个新的快照。此条件可以由用户配置 Redis 实例来控制,也可以在运行时修改而无需重新启动服务器。快照作为包含整个数据集的单个 .rdb 文件生成。

    但是这存在两个问题

    • 写入性能
    • 写入过程,结构改变怎么办

    RDB 问题的解决

    问题的解决是使用 fork 函数,使得由子线程来进行写入操作,fork 函数使用了我们熟悉的COW(Copy-On-Write)机制。

    1297993-20200401153737798-1129263257.png

    所以 快照持久化 可以完全交给 子进程 来处理,父进程 则继续 处理客户端请求。子进程 做数据持久化,它 不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是 父进程 不一样,它必须持续服务客户端请求,然后对 内存数据结构进行不间断的修改。

    这个时候就会使用操作系统的 COW 机制来进行 数据段页面 的分离。数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复 制一份分离出来,然后 对这个复制的页面进行修改。这时 子进程 相应的页面是 没有变化的,还是进程产生时那一瞬间的数据。

    子进程因为数据没有变化,它能看到的内存里的数据在进程产生的一瞬间就凝固了,再也不会改变,这也是为什么 Redis 的持久化 叫「快照」的原因。接下来子进程就可以非常安心的遍历数据了进行序列化写磁盘了。

    这里贴出RDB文件的结构图:

    AOF

    AOF则更像是bin log 日志。 例如进行以下操作 :

    redis 127.0.0.1:6379> set key1 Hello
    OK
    redis 127.0.0.1:6379> append key1 " World!"
    (integer) 12
    redis 127.0.0.1:6379> del key1
    (integer) 1
    redis 127.0.0.1:6379> del non_existing_key
    (integer) 0
    
    

    那么文件中记录的内容则是 :

    $ cat appendonly.aof 
    *2
    $6
    SELECT
    $1
    0
    *3
    $3
    set
    $4
    key1
    $5
    Hello
    *3
    $6
    append
    $4
    key1
    $7
    World!
    *2
    $3
    del
    $4
    key1
    

    AOF重写

    Redis 在长期运行的过程中,AOF 的日志会越变越长。如果实例宕机重启,重放整个 AOF 日志会非常耗时,导致长时间 Redis 无法对外提供服务。所以需要对 AOF 日志 "瘦身"。

    Redis 提供了 bgrewriteaof 指令用于对 AOF 日志进行瘦身。其 原理 就是 开辟一个子进程 对内存进行 遍历 转换成一系列 Redis 的操作指令,序列化到一个新的 AOF 日志文件 中。序列化完毕后再将操作期间发生的 增量 AOF 日志 追加到这个新的 AOF 日志文件中,追加完毕后就立即替代旧的 AOF 日志文件了,瘦身工作就完成了。

    Redis 4.0 混合持久化

    重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。

    Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是 自持久化开始到持久化结束 的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小:

    1297993-20200401155237746-1080411354.png

    RDB 和 AOF 的优缺点

    官方文档罗列地很清楚 : https://redis.io/topics/persistence RDB 优点 :

    • 灾后恢复比AOF方式快
    • fork线程完成IO写入不阻塞父线程对请求的响应,提高了性能 RDB 缺点 :
    • 由于是快照,那么就存在数据丢失
    • fork 函数在调用时是阻塞的,当数据库很大时CPU性能不足会阻塞接受用户请求。

    RDB needs to fork() often in order to persist on disk using a child process. Fork() can be time consuming if the dataset is big, and may result in Redis to stop serving clients for some millisecond or even for one second if the dataset is very big and the CPU performance not great. AOF also needs to fork() but you can tune how often you want to rewrite your logs without any trade-off on durability.

    AOP 优点 :

    • 更具持久化,拥有多个持久选项 : 1. no fsync 2. fsync every second 3. 每查询一次就 fsync 一次
    • AOF log 是顺序写,即使出现磁盘满了或其他原因,导致log 出现不完整,也可以通过工具进行修复。
    • AOF 拥有易于理解的记录格式

    AOF 缺点 :

    • 同等数据下,AOF的文件往往更大
    • 恢复较RDB慢

    补充

    计算机持久化的过程视图如下 :

    1297993-20200401151046445-1756000634.png

    参考资料

    • https://redis.io/topics/persistence
    • http://oldblog.antirez.com/post/redis-persistence-demystified.html
    • https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/Redis/redis-collection/Redis(7)%E2%80%94%E2%80%94%E6%8C%81%E4%B9%85%E5%8C%96.md(必看)
    • 《redis 设计与实现》
  • 相关阅读:
    oracle性能调优
    oracle常用函数
    plsql的安装与使用
    WSAIoctl
    SQL中大概有这么几种JOIN
    如何取分组最大值记录
    having
    MSSQL—按照某一列分组后取前N条记录
    sql之left join、right join、inner join的区别
    delphi 接收心跳包怎么写
  • 原文地址:https://www.cnblogs.com/Benjious/p/12613722.html
Copyright © 2011-2022 走看看