【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

Redis 原理与实战

Java 从 0 到架构师目录:【Java从0到架构师】学习记录

参考:Redis 中两种持久化机制详解

持久化

Redis 所有的数据都是保存在内存中

  • 如果进行了持久化,对数据的更新将异步或者同步的保存到磁盘上
  • 持久化可以避免数据丢失,对数据进行备份,还可以还原指定时间的数据

持久化的方式

  • 快照:MySQL dump、Redis RDB、Oracle dump
  • 写日志:MySQL Binlog、Redis AOF

混合持久化内容的 AOF 文件:

appendonly yes # 开启aof模式
aof-use-rdb-preamble yes # 使用rdb和aof的混合模式, 高版本默认开启

Redis 持久化 - RDB

【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)
触发方式:

  • save(同步):如果存在老的 rdb 文件,新的文件会替换老的文件
  • bgsave(异步):Redis 会调用 fork 来创建一个子进程
  • 自动配置:在配置文件中配置快照触发的条件
    saev 900 1
    save 300 10
    save 60 10000
    

    save 900 1 表示 900s 内,执行了 1次 数据库操作则自动创建快照,以此类推

触发机制

  • 全量复制
  • debug reload
  • shutdown

相关配置:

save 900 1 # 15分钟内有1个key进行修改
save 300 10 # 5分钟类有10个key进行修改
save 60 10000 # 1分钟内有10000个key进行修改

dbfilename dump_6379.rdb  # 备份文件
dir /usr/local/redis-5.0.8/data # 备份目录
stop-writes-on-bgsave-error yes # 在出现错误的时候终止rdb备份, 默认yes
rdbcompression yes # 是否进行压缩, 默认yes
rdbchecksum yes # 是否进行检查sum值校验, 默认yes

RDB 方式的不足之处:耗时,耗费 IO 性能

Redis 持久化 - AOF

【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)
AOF 的三种策略:

  • always:每个 redis 写命令都要同步写入硬盘,严重降低 redis 速度(慎用)
    该策略不会丢失数据,但是 IO 开销很大
  • everysec:每秒同步一次缓冲区的命令到硬盘(推荐,也是默认策略)
    该策略和不使用持久化时的性能几乎无差别,即时系统奔溃也最多丢失 1 秒的数据
  • no:由操作系统决定何时将缓冲区的命令写到硬盘(不推荐)
    该策略是不可控的

AOF 文件重写机制

AOF 方式会使得持久化的文件变的越来越大,AOF 重写机制可以在一定程度下减少磁盘占用量
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)
客户端方式执行重写:BGREWRITEAOF

服务器配置自动重写:

appendonly yes # 是否开启aof文件模式
appendfilename "appendonly-6379.aof" # aof文件名称
appendfsync everysec # aof策略模式
dir usr/local/redis-5.0.8/data # 数据存储路径
no-appendfsync-on-rewrite yes # 在重写的时候, 不要执行aof操作
auto-aof-rewrite-percentage 100 # 自动重写的百分比
auto-aof-rewrite-min-size 64mb # 重写的大小配置
# 当AOF文件体积大于 64M,并且AOF文件的体积比上一次重写之后体积大了 100%(1倍) 时,自动触发重写

Redis 高可用

Redis 主从复制

单击的问题:机器故障引起单点故障,容量达到瓶颈、QPS 达到瓶颈

QPS (Queries Per Second):每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,即每秒的响应请求数,也就是最大吞吐能力

主从复制:

  • 一个 Master 可以有多个 Slave
  • 一个 Slave 只能有一个 Master
  • 数据流向是单向的,只能从 Master 流向 Slave
    只有 Master 可以进行写的操作,然后将数据复制到 Slave
    【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

主从复制的作用:

  • 避免单点故障
  • 读写分离:Master 节点写数据,然后复制到 Slave 节点,Slave 节点读数据
    (默认情况下 Slave 节点无法写数据)
  • 一主多从
  • 多副本

搭建主从复制环境

配置文件:

port 6380
daemonize yes
pidfile  /var/run/redis-6380.pid
logfile 6380.log
dbfilename dump_6380.rdb
dir /usr/local/redis-5.0.8/data/
# bind 192.168.52.128
# 局域网连接要指定 -h: redis-cli -h 192.168.52.128

目前情景:开启了两台 Redis 服务器,分别是 127.0.0.1:6379、127.0.0.1:6380,希望 6379 作为 Master 节点,6380 作为 Slave 节点,开启主从复制
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

  • 方法1:客户端主动执行

    # 以从服务器的身份来执行以下命令的
    # 直接从6379服务端口Master进行数据复制, 自身的数据清空, 然后再从Master复制数据
    slaveof 127.0.0.1 6379
    

    info replication 可以查看当前服务器的角色是 master 还是 slave

    # 脱离 slave 节点的身份, 但是数据会保留
    slaveof no one
    
  • 方法2:服务器配置自动成为 slave 节点

    replicaof 192.168.52.128 6379
    replica-read-only yes # 从节点只读,不能写
    

全量复制和部分复制

全量复制:
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)
部分复制:
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

Redis 哨兵 (Sentinel)

主从复制在高可用中的问题:

  • 手动故障转移:Master 节点下线后,Slave 不会自动变成 Master
  • 写能力和存储能力受限

哨兵机制集群 - 架构图:
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

搭建哨兵集群环境

哨兵机制架构规划:
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)

配置开启主从节点:

# 主节点配置 redis_7000.conf
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile 7000.log
dir /usr/local/redis-5.0.8/data/
# 从节点配置  redis_7001.conf
port 7001
daemonize yes
pidfile  /var/run/redis-7001.pid
logfile 7001.log
dir /usr/local/redis-5.0.8/data/
replicaof 127.0.0.1 7000
#  redis_7002.conf
port 7002
daemonize yes
pidfile /var/run/redis-7002.pid
logfile 7002.log
dir /usr/local/redis-5.0.8/data/
replicaof 127.0.0.1 7000

配置开启 sentinel 监控主从节点:

# sentinel_26379.conf
port 26379
daemonize yes
pidfile /var/run/redis-sentinel-26379.pid
logfile "26379.log"
dir /usr/local/redis-5.0.8/data/
# 告诉sentinel去监听地址为ip:port的一个master, 2个sential认为一个master失效才会真正失效
sentinel monitor mymaster 127.0.0.1 7000 2
# sentinel判断失效的时间
sentinel down-after-milliseconds mymaster 30000
# 最多1个slave对master进行同步
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
# sentinel_26380.conf
port 26380
daemonize yes
pidfile /var/run/redis-sentinel-26380.pid
logfile "26380.log"
dir /usr/local/redis-5.0.8/data/
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
protected-mode no
# sentinel_26381.conf
port 26381
daemonize yes
pidfile /var/run/redis-sentinel-26381.pid
logfile "26381.log"
dir /usr/local/redis-5.0.8/data/
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
protected-mode no

开启主从节点,哨兵节点:

# 启动主从节点服务器
bin/redis-server conf/redis_7000.conf
bin/redis-server conf/redis_7001.conf
bin/redis-server conf/redis_7002.conf

# 启动哨兵节点服务器
bin/redis-sentinel conf/sentinel_26379.conf 
bin/redis-sentinel conf/sentinel_26380.conf 
bin/redis-sentinel conf/sentinel_26381.conf 

通过查看日志可以看到监控信息:
【Java从0到架构师】Redis - 持久化(RBD、AOF)、高可用(主从复制、哨兵机制)
然后进行一些操作,例如结束某个 redis-server:

redis-cli -p 7000 shutdown

然后查看主从节点信息:

# 在 redis-cli 执行以下操作可以查看主从节点信息
info replication

通过哨兵机制,实现了服务端高可用和客户端高可用

上一篇:Redis面试题(一)


下一篇:三千字介绍Redis主从+哨兵+集群