zoukankan      html  css  js  c++  java
  • Redis AOF持久化(二)

    1、AOF持久化的配置

    AOF持久化,默认是关闭的,默认是打开RDB持久化

    appendonly yes,可以打开AOF持久化机制,在生产环境里面,一般来说AOF都是要打开的,除非你说随便丢个几分钟的数据也无所谓

    打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再fsync一下

    而且即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为aof数据比较完整

    可以配置AOF的fsync策略,有三种策略可以选择,一种是每次写入一条数据就执行一次fsync; 一种是每隔一秒执行一次fsync; 一种是不主动执行fsync

    always: 每次写入一条数据,立即将这个数据对应的写日志fsync到磁盘上去,性能非常非常差,吞吐量很低; 确保说redis里的数据一条都不丢,那就只能这样了

    mysql -> 内存策略,大量磁盘,QPS到多少,一两k。QPS,每秒钟的请求数量
    redis -> 内存,磁盘持久化,QPS到多少,单机,一般来说,上万QPS没问题

    everysec: 每秒将os cache中的数据fsync到磁盘,这个最常用的,生产环境一般都这么配置,性能很高,QPS还是可以上万的

    no: 仅仅redis负责将数据写入os cache就撒手不管了,然后后面os自己会时不时有自己的策略将数据刷入磁盘,不可控了

    2、AOF持久化的数据恢复实验

    (1)先仅仅打开RDB,写入一些数据,然后kill -9杀掉redis进程,接着重启redis,发现数据没了,因为RDB快照还没生成
    (2)打开AOF的开关,启用AOF持久化
    (3)写入一些数据,观察AOF文件中的日志内容

    在appendonly.aof文件中,可以看到刚写入的日志,他们就是先写入到os cache的,然后1s后才fsync到磁盘中,只有fsync到磁盘中才是安全的,光是在os cache中,

    机器重新启动,就什么都没有了。 

    (4)kill -9杀掉进程,重新启动redis,数据被恢复回来。就是从aof文件中恢复回来的

    redis进程启动的时候,直接就会从appendonly.aof中加载日志,把内存中的数据恢复回来。

    3、AOF rewrite

    redis中的数据其实有限的,很多数据可能会自动过期,可能会被用户删除,可能会被redis用缓存清除的算法清理掉

    redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中

    所以可能很多之前的已经被清理掉的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀,到很大很大

    所以AOF会自动在后台每隔一定时间做rewrite操作,比如日志里已经存放了针对100w数据的写日志了; 

    redis内存只剩下10万; 基于内存中当前的10万数据构建一套最新的日志,到AOF中;

    覆盖之前的老日志; 确保AOF日志文件不会过大,保持跟redis内存数据量一致

    redis 2.4之前,还需要手动,开发一些脚本,crontab,通过BGREWRITEAOF命令去执行AOF rewrite,但是redis 2.4之后,会自动进行rewrite操作

    在redis.conf中,可以配置rewrite策略

    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb

    比如说上一次AOF rewrite之后,是128mb

    然后就会接着128mb继续写AOF的日志,如果发现增长的比例,超过了之前的100%,256mb,就可能会去触发一次rewrite

    但是此时还要去跟min-size,64mb去比较,256mb > 64mb,才会去触发rewrite

    (1)redis fork一个子进程   

    (2)子进程基于当前内存中的数据,构建日志,开始往一个新的临时的AOF文件中写入日志
    (3)redis主进程,接收到client新的写操作之后,在内存中写入日志,同时新的日志也继续写入旧的AOF文件
    (4)子进程写完新的日志文件之后,redis主进程将内存中的新日志再次追加到新的AOF文件中
    (5)用新的日志文件替换掉旧的日志文件

    4、AOF破损文件的修复

    如果redis在append数据到AOF文件时,机器宕机了,可能会导致AOF文件破损

    用redis-check-aof --fix命令来修复破损的AOF文件

    5、AOF和RDB同时工作

    (1)如果RDB在执行snapshotting操作,那么redis不会执行AOF rewrite; 如果redis再执行AOF rewrite,那么就不会执行RDB snapshotting
    (2)如果RDB在执行snapshotting,此时用户执行BGREWRITEAOF命令,那么等RDB快照生成之后,才会去执行AOF rewrite
    (3)同时有RDB snapshot文件和AOF日志文件,那么redis重启的时候,会优先使用AOF进行数据恢复,因为其中的日志更完整

    (1)在有rdb的dump和aof的appendonly的同时,rdb里也有部分数据,aof里也有部分数据,这个时候其实会发现,rdb的数据不会恢复到内存中
    (2)我们模拟让aof破损,然后fix,有一条数据会被fix删除
    (3)再次用fix得aof文件去重启redis,发现数据只剩下一条了

    数据恢复完全是依赖于底层的磁盘的持久化的,主要rdb和aof上都没有数据,那就没了

    1、企业级的持久化的配置策略

    在企业中,RDB的生成策略,用默认的也差不多

    save 60 10000:如果你希望尽可能确保说,RDB最多丢1分钟的数据,那么尽量就是每隔1分钟都生成一个快照,低峰期,数据量很少,也没必要

    10000->生成RDB,1000->RDB,这个根据你自己的应用和业务的数据量,你自己去决定

    AOF一定要打开,fsync,everysec

    auto-aof-rewrite-percentage 100: 就是当前AOF大小膨胀到超过上次100%,上次的两倍
    auto-aof-rewrite-min-size 64mb: 根据你的数据量来定,16mb,32mb

    2、企业级的数据备份方案

    RDB非常适合做冷备,每次生成之后,就不会再有修改了

    数据备份方案

    (1)写crontab定时调度脚本去做数据备份

    (2)每小时都copy一份rdb的备份,到一个目录中去,仅仅保留最近48小时的备份

    (3)每天都保留一份当日的rdb的备份,到一个目录中去,仅仅保留最近1个月的备份

    (4)每次copy备份的时候,都把太旧的备份给删了

    (5)每天晚上将当前服务器上所有的数据备份,发送一份到远程的云服务上去

    目录:/usr/local/redis

    每小时copy一次备份,删除48小时前的数据

    crontab -e

    sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh

    cur_date=`date +%Y%m%d%k`
    rm -rf /usr/local/redis/snapshotting/$cur_date
    mkdir /usr/local/redis/snapshotting/$cur_date
    cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
    
    del_date=`date -d -48hour +%Y%m%d%k`
    rm -rf /usr/local/redis/snapshotting/$del_date
    

      每天copy一次备份

    crontab -e
    
    0 0 * * * sh /usr/local/redis/copy/redis_rdb_copy_daily.sh
    
    redis_rdb_copy_daily.sh
    
    #!/bin/sh 
    
    cur_date=`date +%Y%m%d`
    rm -rf /usr/local/redis/snapshotting/$cur_date
    mkdir /usr/local/redis/snapshotting/$cur_date
    cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
    
    del_date=`date -d -1month +%Y%m%d`
    rm -rf /usr/local/redis/snapshotting/$del_date
    

       每天一次将所有数据上传一次到远程的云服务器上去

    3、数据恢复方案

    (1)如果是redis进程挂掉,那么重启redis进程即可,直接基于AOF日志文件恢复数据

    fsync everysec,最多就丢一秒的数

    (2)如果是redis进程所在机器挂掉,那么重启机器后,尝试重启redis进程,尝试直接基于AOF日志文件进行数据恢复

    AOF没有破损,也是可以直接基于AOF恢复的

    AOF append-only,顺序写入,如果AOF文件破损,那么用redis-check-aof fix

    (3)如果redis当前最新的AOF和RDB文件出现了丢失/损坏,那么可以尝试基于该机器上当前的某个最新的RDB数据副本进行数据恢复

    当前最新的AOF和RDB文件都出现了丢失/损坏到无法恢复,一般不是机器的故障,人为

    大数据系统,hadoop,有人不小心就把hadoop中存储的大量的数据文件对应的目录,rm -rf一下,/var/redis/6379下的文件给删除了

    找到RDB最新的一份备份,小时级的备份可以了,小时级的肯定是最新的,copy到redis里面去,就可以恢复到某一个小时的数据

     appendonly.aof + dump.rdb,优先用appendonly.aof去恢复数据,但是我们发现redis自动生成的appendonly.aof是没有数据的

    我们自己的dump.rdb是有数据的,但是明显没用我们的数据

    redis启动的时候,自动重新基于内存的数据,生成了一份最新的rdb快照,直接用空的数据,覆盖掉了我们有数据的,拷贝过去的那份dump.rdb

    停止redis之后,其实应该先删除appendonly.aof,然后将我们的dump.rdb拷贝过去,然后再重启redis

    删除了appendonly.aof,但是因为打开了aof持久化,redis就一定会优先基于aof去恢复,即使文件不在,那就创建一个新的空的aof文件

    停止redis,暂时在配置中关闭aof,然后拷贝一份rdb过来,再重启redis,数据能不能恢复过来,可以恢复过来

    再关掉redis,手动修改配置文件,打开aof,再重启redis,数据又没了,空的aof文件,所有数据又没了

    在数据安全丢失的情况下,基于rdb冷备,如何完美的恢复数据,同时还保持aof和rdb的双开

    正确方法:

    1.停止redis,2.关闭aof,3.拷贝rdb备份,4.重启redis,确认数据恢复,5.直接在命令行热修改redis配置,打开aof,这个redis就会将内存中的数据对应的日志,写入aof文件中

    此时aof和rdb两份数据文件的数据就同步了

    redis config set热修改配置参数,可能配置文件中的实际的参数没有被持久化的修改,再次停止redis,手动修改配置文件,打开aof的命令,再次重启redis

    (4)如果当前机器上的所有RDB文件全部损坏,那么从远程的云服务上拉取最新的RDB快照回来恢复数据

    (5)如果是发现有重大的数据错误,比如某个小时上线的程序一下子将数据全部污染了,数据全错了,那么可以选择某个更早的时间点,对数据进行恢复

    举个例子,12点上线了代码,发现代码有bug,导致代码生成的所有的缓存数据,写入redis,全部错了

    找到一份11点的rdb的冷备,然后按照上面的步骤,去恢复到11点的数据,

  • 相关阅读:
    LeetCode120 Triangle
    LeetCode119 Pascal's Triangle II
    LeetCode118 Pascal's Triangle
    LeetCode115 Distinct Subsequences
    LeetCode114 Flatten Binary Tree to Linked List
    LeetCode113 Path Sum II
    LeetCode112 Path Sum
    LeetCode111 Minimum Depth of Binary Tree
    Windows下搭建PHP开发环境-WEB服务器
    如何发布可用于azure的镜像文件
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/11285646.html
Copyright © 2011-2022 走看看