redis之持久化、RDB、AOF、主从复制及Redis-Sentinel

1、持久化

1.1、定义

redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上

1.2、持久化的实现方式
方式一(快照): 
某时某刻数据的一个完成备份
mysql的Dump
redis的RDB

方式二(写日志):
任何操作记录日志,要恢复数据,只要把日志重新走一遍即可
mysql的 Binlog
Hhase的 HLog
Redis的 AOF

2、RDB

2.1、定义

在这里插入图片描述

2.2、触发机制(主要三种方式)
方式一:
save(同步)
1、客户端执行save命令 ---> redis服务端 ---> 同步创建RDB二进制文件
2、会造成redis的阻塞(数据量非常大的时候)
3、文件策略: 如果老的RDB存在,会替换老的
4、复杂度 o(n)

方式二:
bgsave(异步,Backgroud saving started)
1、客户端执行save命令 ---> redis服务端 ---> 异步创建RDB二进制文件(fork函数生成一个子进程(fork会阻塞reids),执行createRDB,执行成功,返回给reids消息)
2、此时访问redis,会正常响应客户端
3、文件策略: 跟save相同,如果老的RDB存在,会替换老的
4、复杂度 o(n)

方式三:
自动(通过配置)
配置   seconds   changes
save   900        1
save   300        10
save   60         10000
如果60s中改变了1w条数据,自动生成rdb
如果300s中改变了10条数据,自动生成rdb
如果900s中改变了1条数据,自动生成rdb

以上三条符合任意一条,就自动生成rdb,内部使用bgsave

# 配置
save 900 1           # 配置一条
save 300 10          # 配置一条
save 60 10000        # 配置一条
dbfilename dump.rdb  # rdb文件的名字,默认为dump.rdb
dir ./               # rdb文件存在当前目录

stop-writes-on-bgsave-error yes  # 如果bgsave出现错误,是否停止写入,默认为yes
rdbcompression yes               # 采用压缩格式
rdbchecksum yes                  # 是否对rdb文件进行校验和检验

# 最佳配置
save 900 1 
save 300 10 
save 60 10000 
dbfilename dump-${port}.rdb      # 以端口号作为文件名,可能一台机器上很多reids,不会乱
dir /bigdiskpath                 # 保存路径放到一个大硬盘位置目录
stop-writes-on-bgsave-error yes  # 出现错误停止
rdbcompression yes               # 压缩
rdbchecksum yes                  # 校验
2.3、触发机制(不容忽略的方式)
1、全量复制  # 没有执行save和bgsave,没有添加rdb策略,还会生成rdb文件,如果开启主从复制,主会自动生成rdb
2、debug reload  # debug级别的重启,不会将内存中的数据清空
3、shutdown save  # 关闭会触发rdb的生成

3、AOF

3.1、RDB存在的问题
耗时,耗性能
不可控,可能会丢失数据
3.2、定义

客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复

3.3、AOF的三种策略
日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上

具体策略如下:
always: redis –> 写命令刷新的缓冲区 —> 每条命令fsync到硬盘 —> AOF文件
everysec(默认值): redis —> 写命令刷新的缓冲区 —> 每秒把缓冲区fsync到硬盘 –> AOF文件
no: redis —> 写命令刷新的缓冲区 —> 操作系统决定,缓冲区fsync到硬盘 –> AOF文件
命令alwayseverysecno
优点不丢失数据每秒一次fsync,丢失1秒数据不用管
缺点IO开销大,一般的sata盘只有几百TPS丢1秒数据不可控
3.4、AOF 重写

随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题

原生AOF                          AOF重写
set hello world
set hello java               set hello hehe
set hello hehe

incr counter                 set counter 2
incr counter

rpush mylist a
rpush mylist b               rpush mylist a b c
rpush mylist c

本质就是把过期的,无用的,重复的,可以优化的命令,来优化
这样可以减少磁盘占用量,加速恢复速度

3.4.1、实现方式
bgrewriteaof
客户端向服务端发送bgrewriteaof命令,服务端会起一个fork进程,完成AOF重写
3.4.2、AOF重写配置
配置名含义
auto-aof-rewrite-min-sizeAOF文件重写需要尺寸
auto-aof-rewrite-percentageAOF文件增长率
统计名含义
aof_current_sizeAOF当前尺寸(单位:字节)
aof_base_sizeAOF上次启动和重写的尺寸(单位:字节)
自动触发时机(两个条件同时满足):
aof_current_size>auto-aof-rewrite-min-size: 当前尺寸大于重写需要尺寸
(aof_current_size-aof_base_size)/aof_base_size>auto-aof-rewrite-percentage: (增长率)当前尺寸减去上次重写的尺寸,除以上次重写的尺寸如果大于配置中的增长率
3.4.3、重写流程

在这里插入图片描述

3.4.4、配置
appendonly yes  # 将该选项设置为yes,打开
appendfilename "appendonly-${port}.aof"  # 文件保存的名字
appendfsync everysec  # 采用第二种策略
dir /bigdiskpath  # 存放的路径
no-appendfsync-on-rewrite yes  # 在aof重写的时候,是否要做aof的append操作,因为aof重写消耗性能,磁盘消耗,正常aof写磁盘有一定的冲突,这段期间的数据,允许丢失

4、RDB和AOF的选择

4.1、rdb和aof的比较
命令rdbaof
启动优先级高(挂掉重启,会加载aof的数据)
体积
恢复速度
数据安全性丢数据根据策略决定
轻重
4.2、rdb最佳策略
rdb关掉,主从操作时
集中管理: 按天,按小时备份数据
主从配置,从节点打开
4.3、aof最佳策略
: 缓存和存储,大部分情况都打开,aof重写集中管理
everysec: 通过每秒刷新的策略
4.4、最佳策略
小分片: 每个redis的最大内存为4g
缓存或存储: 根据特性,使用不通策略
时时监控硬盘.内存,负载网络等
有足够内存

5、主从复制

机器故障,容量瓶颈,QPS瓶颈
一主一从,一主多从
做读写分离
做数据副本
扩展数据性能
一个maskter可以有多个slave
一个slave只能有一个master
数据流向是单向的,从master到slave
5.1、原理
1、副本库通过slaveof 127.0.0.1 6379命令,连接主库,并发送SYNC给主库 
2、主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3、副本库接收后会应用RDB快照
4、主库会陆续将中间产生的新的操作,保存并发送给副本库
5、到此,我们主复制集就正常工作了
6、再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.
7、所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
8、如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9、主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的
5.2、主库是否要开启持久化
如果不开有可能,主库重启操作,造成所有主从数据丢失!
5.3、辅助配置(主从数据一致性配置)
min-slaves-to-write 1
min-slaves-max-lag 3
那么在从服务器的数量少于一个或者三个从服务器的延迟(lag)值都大于或等于3秒时,主服务器将拒绝执行写命令
5.4、主从复制的配置
5.4.1、slave 命令
6380是从,6379是主
在6380上执行(去从库配置,配置主库)

slaveof 127.0.0.1 6379  # 异步
slaveof no one          # 取消复制,不会把之前的数据清除
5.4.2、配置文件
slaveof ip port      # 配置从节点ip和端口
slave-read-only yes  # 从节点只读,因为可读可写,数据会乱

mkdir -p redis1/conf redis1/data redis2/conf redis2/data redis3/conf redis3/data
vim redis.conf

daemonize no
pidfile redis.pid
bind 0.0.0.0
protected-mode no
port 6379
timeout 0
logfile redis.log
dbfilename dump.rdb
dir /data
slaveof 127.0.0.1 6379
slave-read-only yes


cp redis.conf /home/redis2/conf/

docker run -p 6379:6379 --name redis_6379 -v /home/redis1/conf/redis.conf:/etc/redis/redis.conf -v /home/redis1/data:/data -d redis redis-server /etc/redis/redis.conf
docker run -p 6378:6379 --name redis_6378 -v /home/redis2/conf/redis.conf:/etc/redis/redis.conf -v /home/redis2/data:/data -d redis redis-server /etc/redis/redis.conf
docker run -p 6377:6379 --name redis_6377 -v /home/redis3/conf/redis.conf:/etc/redis/redis.conf -v /home/redis3/data:/data -d redis redis-server /etc/redis/redis.conf

info replication
5.4.3、配置总结
方式一:
	在从库执行 SLAVEOF 127.0.0.1 6379
	断开关系 slaveof no one
	
方式二: 配置文件(配在从库的配置文件中)
	slaveof 127.0.0.1 6379
	slave-read-only yes
5.5、故障处理
slave故障
master故障
5.6、主从复制常见问题
1、读写分离
读流量分摊到从节点
可能遇到问题: 复制数据延迟,读到过期数据,从节点故障

2、主从配置不一致
maxmemory不一致: 丢失数据
数据结构优化参数: 主节点做了优化,从节点没有设置优化,会出现一些问题

3、规避全量复制
第一次全量复制,不可避免: 小主节点,低峰(夜间)
节点运行id不匹配: 主节点重启(运行id变化)
复制挤压缓冲区不足: 增大复制缓冲区大小,rel_backlog_size

4、规避复制风暴
单主节点复制风暴,主节点重启,所有从节点复制

6、Redis-Sentinel

6.1、主从复制高可用
主从复制存在的问题:
1、主从复制,主节点发生故障,需要做故障转移,可以手动转移: 让其中一个slave变成master
2、主从复制,只能主写数据,所以写能力和存储能力有限
6.2、架构说明

可以做故障判断,故障转移,通知客户端(其实是一个进程),客户端直接连接sentinel的地址
在这里插入图片描述

1、多个sentinel发现并确认master有问题
2、选举出一个sentinel作为领导
3、选取一个slave作为新的master
4、通知其余slave成为新的master的slave
5、通知客户端主从变化
6、等待老的master复活成为新master的slave
6.3、安装配置
1、配置开启主从节点
2、配置开启sentinel监控主节点(sentinel是特殊的redis)
3、应该是多台机器
# 配置开启sentinel监控主节点
mkdir -p redis4/conf redis4/data redis5/conf redis5/data redis6/data redis6/conf

vi sentinel.conf

port 26379
daemonize yes
dir data
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000


docker run -p 26379:26379 --name redis_26379 -v /home/redis4/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis4/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf

docker run -p 26378:26379 --name redis_26378 -v /home/redis5/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis5/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf

docker run -p 26377:26379 --name redis_26377 -v /home/redis6/conf/sentinel.conf:/etc/redis/sentinel.conf -v /home/redis6/data:/data -d redis redis-sentinel /etc/redis/sentinel.conf


redis-sentinel sentinel.conf

info
配置会重写,自动发现slave
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel monitor <master-name> <ip> <redis-port> <quorum>
告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效

sentinel auth-pass <master-name> <password>
设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同

sentinel down-after-milliseconds <master-name> <milliseconds> 
这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的,单位是毫秒,默认为30秒

sentinel parallel-syncs <master-name> <numslaves> 
这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用,可以通过将这个值设为1来保证每次只有一个slave处于不能处理命令请求的状态

sentinel failover-timeout <master-name> <milliseconds>
failover-timeout 可以用在以下这些方面:
1、同一个sentinel对同一个master两次failover之间的间隔时间
2、当一个slave从一个错误的master那里同步数据开始计算时间,直到slave被纠正为向正确的master那里同步数据时
3、当想要取消一个正在进行的failover所需要的时间
4、当进行failover时,配置所有slaves指向新的master所需的最大时间,不过即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了

操作步骤

1、搭一个一主两从
# 创建三个配置文件:
# 第一个是主配置文件
daemonize yes
pidfile /var/run/redis.pid
port 6379
dir "/opt/soft/redis/data"
logfile “6379.log”

# 第二个是从配置文件
daemonize yes
pidfile /var/run/redis2.pid
port 6378
dir "/opt/soft/redis/data2"
logfile “6378.log”
slaveof 127.0.0.1 6379
slave-read-only yes

# 第三个是从配置文件
daemonize yes
pidfile /var/run/redis3.pid
port 6377
dir "/opt/soft/redis/data3"
logfile “6377.log”
slaveof 127.0.0.1 6379
slave-read-only yes

# 把三个redis服务都启动起来
./src/redis-server redis_6379.conf
./src/redis-server redis_6378.conf
./src/redis-server redis_6377.conf


2、搭建哨兵
# sentinel.conf这个文件
# 把哨兵也当成一个redis服务器
创建三个配置文件分别叫sentinel_26379.conf sentinel_26378.conf sentinel_26377.conf

# 当前路径下创建 data1 data2 data3 个文件夹
# 内容如下(需要修改端口,文件地址日志文件名字)
port 26379
daemonize yes
dir ./data3
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel3.log"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

# 启动三个哨兵
./src/redis-sentinel sentinel_26379.conf
./src/redis-sentinel sentinel_26378.conf
./src/redis-sentinel sentinel_26377.conf

# 登陆哨兵
./src/redis-cli -p 26377
# 输入 info 
# 查看哨兵的配置文件被修改了,自动生成的

# 主动停掉主redis 6379,哨兵会自动选择一个从库作为主库
redis-cli -p 6379
shutdown
# 等待原来的主库启动,该主库会变成从库
6.4、客户端连接
import redis
from redis.sentinel import Sentinel

# 连接哨兵服务器(主机名也可以用域名)
# 192.168.1.4:26379
sentinel = Sentinel([('192.168.1.4', 26379),
                     ('192.168.1.4', 26378),
                     ('192.168.1.4', 26377)
		     ],
                    socket_timeout=5)

print(sentinel)
# 获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)

# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)

# 读写分离
# 获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5)
w_ret = master.set('foo', 'bar')

slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
r_ret = slave.get('foo')
print(r_ret)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值