Redis学习(一)之 持久化、主从与哨兵架构

jiaruredis持久化

RDB快照:在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。

你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。比如说, 以下设置会让 Redis 在满足"60秒内有至少有 1000 个键被改动"这一条件时, 自动保存一次数据集:

# save 60 1000 //关闭RDB只需要将所有的save保存策略注释掉即可。
还可以手动执行命令 生成RDB快照 ,进入redis客户端 执行命令 save bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照 到一个新的rdb文件里,并覆盖原有rdb快照文件。
bgsave的写时复制(COW)机制:
Redis 借助操作系统提供的写时复制技术(Copy-On-Write, COW)在生成快照的同时,依然可以正常 处理写命令。简单来说,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。
此时,如果主线程对这些 数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那 么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文 件,而在这个过程中,主线程仍然可以直接修改原来的数据。

AOF( append-only file):
快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失 最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方 式: AOF 持久化,将修改的 每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间 fsync到磁盘)
可以通过修改配置文件来打开 AOF 功能:  # appendonly yes
可以配置 Redis 多久才将数据 fsync 到磁盘一次。 有三个选项:
  • appendfsync always:每次有新命令追加到AOF文件时就执行一次保存 ,非常慢,也非常安全。
  • appendfsync everysec:每秒保存 一次,足够快,并且在故障时只会丢失1秒钟的数据。
  •  appendfsync no:从不 保存,将数据交给操作系统来处理。更快,也更不安全的选择。

推荐(并且也是默认)的措施为每秒 保存 一次, 这种 策略可以兼顾速度和安全性。

AOF重写:AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件

例如,执行了如下几条命令:

 最后重写成:(过程不重要,直接重写为结果6)

 如下两个配置可以控制AOF自动重写频率:

  •  # autoaofrewriteminsize64mb//aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
  •  # autoaofrewritepercentage100//aof文件自上一次重写后文件大小增长了100%则再次触发重写
当然AOF还可以手动重写,进入redis客户端 执行命令 bgrewriteaof 重写AOF;
注意, AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多 影响。

Redis 4.0 混合持久化:

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重 放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。通过如下配置可以开启混合持久化(必须先开启aof):

 # aof‐use‐rdb‐preamble yes

 如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重启效率大幅得到提升。

Redis主从架构:

linux安装redis步骤可以移步这一篇文章:linux环境下安装redis(一)_酒书的博客-CSDN博客_linux下安装redis

参考redis的安装可以发现安装好了一台redis,端口号6379

然后着手搭建主从同步:

注意:搭建之前一定要主从机器的自我保护,不然主机会拒绝连接的

 step1:复制一份redis.conf文件

step2:将相关配置修改为如下值:
port 6380
pidfile / var / run / redis_6380 . pid # pid 进程号写入 pidfile 配置的文件
logfile "6380.log"
dir / usr / local / redis 5.0.3 / data / 6380 # 指定数据存放目录
# 需要注释掉 bind
# bind 127.0.0.1 bind 绑定的是自己机器网卡的 ip ,如果有多块网卡可以配多个 ip ,代表允许客户端通
过机器的哪些网卡 ip 去访问,内网一般可以不配置 bind ,注释掉即可)
// 配置主从复制
replicaof 192.168.0.60 6379 # 从本机 6379 redis 实例复制数据, Redis 5.0 之前使用 slaveof

replicareadonly yes #配置从节点只读 

step3:启动从节点

step4:连接从节点

 step5:测试6379上写数据,6380机器是否同步到相关数据

主从搭建成功,一主一从!!!! 

Redis主从工作原理:

        如果你为master配置了一个slave,不管这个salve是否是第一次连接上master,它都会发送一个PSYNC的命令给master请求复制数据;master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间master会继续接收客户端的请求,它会把这些可能修改数据的请求缓存到内存中;当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后master再将之前缓存在内存中的命令发送给slave。

        当master与salve之间的连接由于某些原因而断开时,slave能够自动重连master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

主从复制(全量复制流程图):

 数据部分复制:

当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。

master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有slave都维护了复制的数据下标offset和master的进程id,因此当网络连接断开后再连接,slave会请求master继续进行未完成的复制,从所记录的数据下标开始;如果master进程id变化了或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

主从复制(部分复制、断点续传)流程图:

如果有很多从节点,为了缓解 主从复制风暴 (多个从节点同时复制主节点导致主节点压力过大),可
以做如 下架构,让部分从节点与从节点(与主节点同步)同步数据:

ps:主从架构当主服务器挂了之后需要运维手动修改某个从节点为主节点,主从架构中的slave的主要功能就是做数据备份使用

Redis哨兵架构:

 sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。

哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)。

哨兵架构搭建步骤:

step1:我在主从基础上再搞一台从机slave6381(步骤可以参考从机6380的搭建)

step2:测试6381可用

 

 现在就是一主二从的架构了,接着搭建哨兵架构

step3:搭建哨兵

在安装好redis之后在redis文件夹下可以看到是有一个sentinel.conf

1、复制一份sentinel.conf:cp sentinel.conf  sentinel-26379.conf

2、将相关配置修改为如下值:

port 26379
daemonize yes
pidfile "/var/run/redis‐sentinel‐26379.pid"
logfile "26379.log"
dir "/usr/local/redis‐5.0.3/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 这个名字随便取,客户端访问时会用

step4:启动sentinel哨兵实例

src/redissentinel   sentinel26379.conf

step5:同理继续配置两个哨兵,端口2638026381,注意上述配置文件里的对应数字都要修改

step6:查看sentinelinfo信息

src/redisclip26379

info

 可以看到一主二从三哨兵搭建完成!!!

sentinel集群都启动完毕后,会将哨兵集群的元数据信息写入所有的sentinel的配置文件里去(追加在文件的最下面),我们查看如下配置文件sentinel-26379.conf,如下所示:

sentinel known replica mymaster 116.62.71.39  6380 # 代表 redis 主节点的从节点信息
sentinel known replica mymaster 116.62.71.39  6381  # 代表 redis 主节点的从节点信息
sentinel known sentinel mymaster 116.62.71.39 26381  xxxxx  # 代表感知到的其它哨兵节点

sentinel knownsentinel mymaster116.62.71.39 26380  xxxxx #代表感知到的其它哨兵节点

如果redis主节点挂了,哨兵集群会重新选举出新的redis主节点,同时会修改所有sentinel节点配置文件的集群元数据信息,同时还会修改sentinel文件里之前配置的mymaster对应的端口,当6379的redis实例再次启动时,哨兵集群根据集群元数据信息就可以将6379端口的redis节点作为从节点加入集群。

哨兵的jedis连接代码:

下面用代码演示:当主节点挂了之后哨兵重新选举,客户端是否能够动态感知

引入依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

配置文件:

 测试controller:

 然后我启动程序调用接口访问:可以看到一直在set值

这个时候我将redis主节点6379给停掉:可以看到会出现短暂的报错

在短暂报错之后,新的主节点选举出来之后就会继续进行set值,如下图所示:

 这个时候我登录6381机器,使用info命令查看集群信息:6381成了master


版权声明:本文为royal1235原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。