Redis RDB、AOF及混合持久化,主从模式,哨兵模式

一、RDB、AOF 及混合持久化详解
1.1 RDB 持久化

RDB 持久化是把当前进程数据生成快照保存在硬盘的过程,触发RDB持久化有两种方式,分别是 手动触发,自动触发。

1.1.1 手动生成RDB快照

进入 redis 客户端 执行 save 或 bgsave 可以生成dump.rdb文件,每一次执行命令就生成新的rdb快照文件,并覆盖原有的 rdb 快照文件。

save 命令 :执行 save 命令的时候会阻塞当前 redis 服务器,直到RDB快照成功生成,内存中的数据量过大的可能造成短时间的阻塞,线上环境不推荐使用。

bgsave 命令:Redis 主进程 fork操作创建子线程,RDB快照生成由子线程负责,完成后结束,阻塞只会在 fork 阶段且时间很短。

1.1.2 自动生成RDB快照(后台使用 bgsave 命令)

默认情况下,Redis 将进程内存数据保存在 dumo.rdb 的二进制文件中。
可以对Redis 进行设置,让它在 “N秒内数据集至少有M个改动” 满足这一条件,自动保存一次数据集。

# redis 默认save 策略
save 900 1  # 900秒只有一次改动,自动保存一次
save 300 10  # 300秒内有10次改动,自动保存一次
save 60 10000  # 60秒内有1万次改动,自动保存一次
#关闭RDB只需要把所有 save 保存策略注释掉即可

除了上面 save 保存策略,还有以下操作也会触发自动保存RDB快照:

1、Redis 从节点执行全量复制操作,主节点会自动执行 bgsave 生成RDB 快照文件发给 从节点.
2、执行 dubug roload 命令重新加载 redis ,也会触发生成 RDB 快照.
3、默认没开启 AOF 持久化时,执行 shutdown 命令也会自动执行 bgsave.
4、kill 服务也会执行 bgsave.

bgsave 的写时复制(COW)机制:

Redis 借助操作系统的写时复制技术(Copy-On-Write,COW),在生成快照的同时,依然可以正常处理写命令。
在这里插入图片描述

1.1.3 RDB 持久化优点

rdb 文件是一个二进制紧凑文件,代表着 redis 某一时段的数据快照,非常适用于备份,全量复制等场景。比如定时 bgsave 备份,把RDB文件拷贝到远程机器或者文件系统中,用于数据恢复。

加载 rdb 快照恢复数据会快于aof 方式.

1.1.4 RDB 持久化缺点

1、RDB持久化数据没办法做到实时持久化/秒级持久化,且每次 bgsave 都要执行fork操作创建子进程,属于重操作,频繁执行成本过高。

2、rdb 快照文件会存在版本演变格式的不同,存在老版本 redis 无法兼容新版本redis的rdb文件。

针对RDB不适合做实时持久化的缺点,Redis 采取了AOF持久化方法解决.

1.2 AOF 持久化

AOF(append only file) 持久化:以独立日志的方式记录写的操作命令,重启 redis 的时候执行 AOF文件恢复数据来达到持久化目的。

1.2.1 开启 aof 持久化(默认不开启):
# 开启aof 持久化
appendonly yes
# aof 文件名
appendfilename " appendonly.aof"
# 保存路径
dir ./

aof 配置开启之后, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾 (会先写入os cache,每隔一段时间fsync硬盘中(fsync策略可配置))。AOF文件名 通过appendfilename 配置 , 默认文件名 appendonly.aof。保存路径和 RDB持久化方式一致,通过dir配置指定。

例如执行 set lwc 666 , aof 文件中对应内容如下:

 *2
$6
SELECT
$1
0
*3
$3
set
$3
lwc
$3
666

上面文件内容为resp协议格式数据,星号后面的数字代表命令有多少个参数,$ 号后面的数字表示有多少字符。
注意: 执行带过期时间的set命令,aof 文件里记录的并不是执行的原始命令,而是记录 key 过期的时间戳.

例如执行 set lwc 666 ex 1000 , aof文件对应内容如下 :

*3
$3
set
$3
lwc
$3
666
*3
$9
PEXPIREAT
$3
lwc
$13
1609596572778
1.2.2 配置 Redis 将数据 fsync 到 硬盘策略:

默认 appendfsync everysec ,推荐使用,速度和安全兼得,只会丢失一秒的数据。

appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全。
appendfsync everysec:每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据。
appendfsync no:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择。
1.2.3 AOF 重写

随着 aof 文件越来越大,就需要对 aof 文件进行重写,到达整理压缩的目的。

会重写哪些内容?

1、进程内已经过期的数据不再写入aof文件
2、重写前的 aof 存在无用的命令,这些命令将不再保留重写后的 aof 文件,只保留最终数据执行的命令
3、多条写命令可以合并成一个,incr readcount , incr readcount , incr readcount ,如这样的命令会重写成 set readcount 3
4、为了单次写命令过大而造成客户端缓冲区溢出,将对于 list set hash zset 等类型操作,以64个元素为界分成多条命令

重写 aof 文件的好处:减少文件占用内存之外,更多是为了客户端重启执行加载 aof 文件的速度更快

1.2.4 AOF 文件重写分为 手动触发跟自动触发

手动触发:客户端执行 bgrewriteaof 命令 将会重写 aof 文件

自动触发,配置自动重写策略:

auto‐aof‐rewrite‐min‐size 64mb # aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
auto‐aof‐rewrite‐percentage 100 # aof文件自上一次重写后文件大小增长了100% 则再次触发重写 64mb 则 128mb

注意:aof 重写也是主线程 fork 出子线程去做(与bgsave相似),对redis正常处理其它命令不会有太大影响。

RDB 跟AOF ,用哪个?

RDB:恢复数据速度快,数据安全性不高,容易丢数据,启动优先级低
AOF: 恢复速度速度慢,数据安全性相对RDB,根据策略决定,启动优先级高

生产环境都可以启动,redis 启动是会优先选择 aof 文件恢复数据,因为 aof 的数据一般会比 rdb 的数据更安全一些。

redis 启动加载持久化文件流程:
在这里插入图片描述

1.3 AOF 混合持久化(Redis 混合持久化)

重启Redis时,很少用RDB快照的方式来恢复内存数据,因为会丢失大量数据,我们通常使用 AOF 日志重放,但是重放 AOF日志性能比 RDB 要慢很多,这样在 redis 实例很大的情况下,重启需要一定的时间。Redis 4.0 为了解决这一问题,加强了AOF并取名叫混合持久化。

配置混合持久化(必须先开启aof) :

aof‐use‐rdb‐preamble yes

开启了混合持久化,AOF 在重写时,不再是只将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入到新的AOF文件,新的文件一开始不叫 appendonly.aof。等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
于是在redis 重启的时候,会先加载 RDB 的内容,然后再重放增量AOF日志就可以替代之前的AOF全量文件重放,效率大大提高。

二、Redis 数据备份策略

1、写 crontab 定时调度脚本,每小时copy一份rdb或aof备份到一个目录中去,仅仅保留最近48个小时的备份
2、每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份
3、每次copy备份的时候,都把太旧的备份给删了
4、每天晚上将当前机器上的备份复制一份到其他机器上,防止机器损坏

只要有 appendonly.aof 和 dump.rdb 就能把数据恢复到内存中。

提示:具体还是备份策略还是要以公司的情况来定

三、Redis 主从结构详解

主从复制指的是将一台 Redis 服务器的数据复制到另一台 Redis 上,前者为主节点(可读写),后者为从节点(只读),主节点可以有多个从节点,也可以没有从节点,但从节点只能有主节点。

本机多实例模拟 redis 主从架构搭建及配置:

1、复制一份redis.conf 文件,并改名为 redis_6380.conf

2、将相关配置修改为如下值:
port 6380
pidfile /var/run/redis_6380.pid  # 把pid进程号写入pidfile配置的文件
logfile "6380.log"
dir ./data/6380  # 数据存在目录

3、配置主从复制(关键配置)
replicaof 127.0.0.1 6379 # 从本机6379的redis 实例复制数据,5.0 版本之前使用 slaveof
replica‐read‐only yes # 配置从节点只读

4、指定主节点的密码
masterauth 123456a

5、启动从节点
./src/redis-server redis_6380.conf

6、连接从节点客户端
./src/redis-cli -a 123456 -p 6380

7、执行 info 查看实例信息
127.0.0.1:6380> info

# Replication
role:slave
master_host:127.0.0.1  # 主节点 ip
master_port:6379 # 主节点 端口号
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:1bef69622bb1ff4051aa7ad0602b1219855149c0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70


8、测试在 6379 端口写数据,然后再看6380实例是否及时同步新修改数据

9、再尝试多配置几个从节点
1.1 主从复制过程原理:

1、slave(从节点)与master(主节点)建立连接,发送sysync同步命令
2、master会开启一个后台进程通过bgsave生成最新的rdb快照文件,同时master主进程会开始收集新的写命令并缓存,然后,master再将之前缓存在内存中的命令发送给slave。
3、slave节点将此文件保存到硬盘。

复制偏移量

主从节点都维护这一个复制偏移量(offset),它代表着当前节点接受数据的字节数,主节点表示接收客户端的字节数,从节点表示接收主节点的字节数,比如从节点接收主节点传来的N 个字节数据时,从节点的offset 会增加 N。

偏移量的作用非常大,它是用来衡量主从节点数据是否一直的唯一标准,如果主从节点的 offset 相等,表明数据一致,否则表明数据不一致。在不一致的情况下,可以根据两个节点的 offset找出从节点的缺少的那部分数据。比如,主节点的 offset 是 500,从节点的 offset是 400,那么主节点在进行数据传输时只需要将 401 ~ 500 传递给从节点即可,这就是部分复制。

复制积压缓冲区

复制积压缓冲区是一个由主节点维护的缓存队列,它具有如下几个特点:

1、由主节点维护
2、固定大小,默认为 1MB,配置参数为:repl-backlog-size
3、是一个先进先出的队列

在命令传播节点,主节点除了将写命令传递给从节点,也会将写命令写入到复制积压缓冲区中,当做一个备份,用于在部分复制流程中。由于它是先进先出的队列,且大小固定,所以他只能保存主节点最近执行的写命令,当主从节点的
offset相差较大时,超出了复制积压缓冲区的范围,则无法进行部分复制,只能进行全量复制了,所以为了能够提高网络中断引起的全量复制,我们需要认真评估复制积压缓冲区的大小,将其适当调大,比如网络中断时间是60s,主节点每秒接收的写命令为100KB,则复制积压缓冲区的平均大小应该为6MB,所以我们可以将其大小设置为6MB,甚至是10MB`,来保证绝大多数中断情况下都可以使用部分复制。

运行 ID(runid)

每个 Redis 节点在启动时都会生成一个运行 ID,即 runid,该 ID 用于唯一标识 Redis 节点,它是一个由
40 位随机的十六进制的字符组成的字符串,通过 info server 命令可以查看节点的 runid

从节点在初次建立连接进行全量复制时(从节点发送 psync ? -1),主节点会将自己的 runid 告知给从节点,从节点将其保存起来。当主从节点断开重连时,从节点会将这个runid发送给主节点,主节点会根据从节点发送的runid 来判断选择何种复制:

1、如果从节点发送的 runid 与当前主节点的
runid一致时,主节点则尝试进行部分复制,当然能不能进行部分复制还要看偏移量是否在复制积压缓冲区
2、如果从节点发送的 runid
与当前主节点的runid 不一致时,则进行全量复制

1.1.2 全量复制

在这里插入图片描述

1.1.3 部分复制

在这里插入图片描述

四、Redis 哨兵高可用架构详解

哨兵是一种特殊的模式,不提供读写服务,用来监控 redis 实例节点。
哨兵架构下 client 端第一次从哨兵找出 redis 的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel 代理访问 redis 的主节点,当 redis 的主节点发生变化,哨兵会第一时间感知到,并且将新的 redis 主节点通知给 client 端。哨兵的原理就是,发送命令给 redis ,再等待 redis 响应,从而达到监听 redis 的效果。(首先 client 端要实现订阅功能,订阅 sentinel 发布的节点变动消息).

1.1 搭建哨兵架构配置
1、修改 sentinel.conf 文件
port 26379
daemonize yes
pidfile "/var/run/redis‐sentinel‐26379.pid"
logfile "26379.log"
dir "/usr/local/redis‐5.0.6/data"
# sentinel monitor <master‐redis‐name> <master‐redis‐ip> <master‐redis‐port> <quorum>
# quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 +1),master才算真正失效
sentinel monitor mymaster 192.168.0.60 6379 2 # mymaster这个名字随便取,客户端访问时会用到

3、启动sentinel哨兵实例
src/redis‐sentinel sentinel‐26379.conf

4、查看sentinel的info信息
src/redis‐cli ‐p 26379
127.0.0.1:26379>info
可以看到Sentinel的info里已经识别出了redis的主从

启动完哨兵之后,哨兵的元数据信息写入所有sentinel的配置文件里去(追加在文件的最下面),

如下:

protected-mode no
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-replica mymaster 127.0.0.1 6380
sentinel current-epoch 
1.2 Jedis 方式连接哨兵实例
public static void main(String[] args) {

        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(20);
        config.setMinIdle(10);
        config.setMinIdle(5);

        //哨兵配置文件里面配置 redis 主节点名称
        String masterName = "mymaster";

        HashSet<String> sentinels = new HashSet<>();
        sentinels.add(new HostAndPort("81.69.233.*",26379).toString());
        sentinels.add(new HostAndPort("81.69.233.*",26380).toString());
        sentinels.add(new HostAndPort("81.69.233.*",26381).toString());

        //JedisSentinelPool其实本质跟JedisPool类似,都是与redis主节点建立的连接池
        //JedisSentinelPool并不是说与sentinel建立的连接池,而是通过sentinel发现redis主节点并与其建立连接

        JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName,sentinels,config,3000,null);
        Jedis jedis = null;
        try {
            jedis  = jedisSentinelPool.getResource();
            System.out.println(jedis.set("sentinel","lwc"));
            jedis.set("lwc1","666");
            jedis.set("lwc2","666");
            jedis.set("lwc3","666");

            Set<String> keys = jedis.keys("*");
            Iterator<String> setKeys = keys.iterator();
            while (setKeys.hasNext()) {
                String str  = setKeys.next();
                System.out.println(str);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池
            if (jedis != null){
                jedis.close();
            }
        }
    }
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Redis 持久化是指将内存中的数据保存到磁盘上,以防止服务器重启或者意外宕机时数据的丢失。Redis提供了两种持久化方式:RDBRedis Database)和AOF(Append Only File)。 RDB是将当前内存中的数据快照保存到磁盘上,它是一个二进制文件,可以通过配置定期或者手动触发生成。RDB持久化方式相对于AOF持久化方式更加紧凑,适合备份和恢复大数据集。但是,RDB持久化方式会导致数据在断电或宕机时的数据丢失。 AOF是将Redis服务器接收到的写操作追加到文件末尾,类似于日志文件,通过重放日志来恢复数据。AOF持久化方式相对于RDB持久化方式更加安全,可以降低数据丢失的风险。但是,AOF持久化方式相对于RDB持久化方式会占用更多的磁盘空间,并且恢复数据的速度相对较慢。 主从复制是指将一个Redis服务器的数据复制到多个从服务器上。主从复制可以实现数据的热备份、读写分离以及负载均衡。主服务器接收到写操作后,会将写操作同步到所有从服务器上,从服务器会将主服务器的数据复制到本地。主从复制可以提高系统的可用性和性能。 哨兵模式是为了解决Redis主从复制中主服务器宕机后自动切换问题而引入的。哨兵是一个独立运行的进程,它会监控主服务器和从服务器的状态。当哨兵检测到主服务器宕机后,会选举一个从服务器作为新的主服务器,并通知其他从服务器切换主服务器。 雪崩是指缓存中大量的数据同时失效,导致大量请求直接访问数据库,造成数据库压力过大。击穿是指某个特定的key失效,导致大量请求同时访问数据库。穿透是指请求的数据在缓存中不存在,也不存在于数据库中。 解决雪崩的办法可以采用多级缓存、缓存预热、限流等方式来减轻数据库的压力。解决击穿的办法可以采用互斥锁、热点数据预加载等方式来保护数据库。解决穿透的办法可以采用布隆过滤器、空结果缓存等方式来避免无效请求直接访问数据库

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不像程序猿的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值