Redis有两种持久化方案:
# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1
save 300 10
save 60 10000
# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes
# RDB文件名称
dbfilename dump.rdb
# 文件保存的路径目录
dir ./
AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:
# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
AOF的命令记录的频率也可以通过redis.conf文件来配:
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
三种策略对比:
配置项 | 刷盘时机 | 优点 | 缺点 |
---|---|---|---|
Always | 同步刷盘 | 可靠性高,几乎不去数据 | 性能影响大 |
everysec | 每秒刷盘 | 性能适中 | 最多丢失1秒数据 |
no | 操作系统控制 | 性能最好 | 可靠性较差,可能丢失大量数据 |
# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb
RDB | AOF | |
---|---|---|
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
系统资源占用 | 高,大量CPU和内存消耗 | 低,主要是磁盘IO资源但AOF重写时会占用大量CPU和内存资源 |
使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
IP | PORT | 角色 |
---|---|---|
192.168.188.112 | 7001 | master |
192.168.188.112 | 7002 | slave |
192.168.188.112 | 7003 | slave |
# 进入/tmp目录
cd /tmp
# 创建目录
mkdir cluster
mkdir 7001 7002 7003
# 开启RDB#
save ""save 3600 1
save 300 100
save 60 10000
# 关闭AOF
appendonly no
sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf
sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf
sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf
# redis实例的声明 IP
replica-announce-ip 192.168.xxx.xxx
# 逐一执行
sed -i '1a replica-announce-ip 192.168.xxx.xxx' 7001/redis.conf
sed -i '1a replica-announce-ip 192.168.xxx.xxx' 7002/redis.conf
sed -i '1a replica-announce-ip 192.168.xxx.xxx' 7003/redis.conf
# 或者一键修改
printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip 192.168.xxx.xxx' {}/redis.conf
#/tmp/cluster目录下
# 第1个
redis-server 7001/redis.conf
# 第2个
redis-server 7002/redis.conf
# 第3个
redis-server 7003/redis.conf
printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-cli -p {} shutdown
slaveof <masterip> <masterport>
slaveof
# 连接 7002
redis-cli -p 7002
# 执行slaveof
slaveof 192.168.188.112 7001
# 连接 7003
redis-cli -p 7003
# 执行slaveof
slaveof 192.168.188.112 7001
# 连接 7001
redis-cli -p 7001
# 查看状态
info replication
127.0.0.1:7001> set num 111
OK
127.0.0.1:7002> set num 111
(error) READONLY You can't write against a read only replica.
127.0.0.1:7003> set num 111
(error) READONLY You can't write against a read only replica.
主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程:
master如何得知salve是第一次来连接呢?有几个重要概念,可以作为判断依据:
因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。
完整流程描述:
slave节点请求增量同步
master节点判断replid,发现不一致,拒绝增量同步
master将完整内存数据生成RDB,发送RDB到slave
slave清空本地数据,加载master的RDB
master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
slave执行接收到的命令,保持与master之间的同步
master怎么知道slave与自己的数据差异在哪里呢?
此时,如果有新的数据写入,就会覆盖数组中的旧数据。不过,旧的数据只要是绿色的,说明是已经被同步到slave的数据,即便被覆盖了也没什么影响。因为未同步的仅仅是红色部分。
如果slave出现网络阻塞,导致master的offset远远超过了slave的offset:
主从同步可以保证主从数据的一致性,非常重要。可以从以下几个方面来优化Redis主从就集群:
在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力
slave节点宕机恢复后可以找master节点同步数据,那master节点宕机怎么办?
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。
一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:
当选出一个新的master后,切换流程如下:
Sentinel的三个作用是什么?
Sentinel如何判断一个redis实例是否健康?
故障转移步骤有哪些?
节点 | IP | PORT |
---|---|---|
s1 | 192.168.188.112 | 27001 |
s2 | 192.168.188.112 | 27002 |
s3 | 192.168.188.112 | 27003 |
cluster-sentinel
三个文件夹,名字分别叫s1、s2、s3
:# 进入/tmp目录
cd /tmp
# 创建目录
mkdir cluster-sentinel
cd cluster-sentinel
mkdir s1 s2 s3
port 27001
sentinel announce-ip 192.168.188.112
sentinel monitor mymaster 192.168.188.112 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/cluster-sentinel/s1"
port 27001
:是当前sentinel实例的端口sentinel monitor mymaster 192.168.188.112 7001 2
:指定主节点信息
mymaster
:主节点名称,自定义,任意写192.168.188.112 7001
:主节点的ip和端口2
:选举mast:er时的quorum值# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf
sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf
# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf
哨兵集群故障转移测试【仅供参考】
redis-cli -p 7001 shutdown
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
sentinel:
master: mymaster
nodes:
- 192.168.188.112:27001
- 192.168.188.112:27002
- 192.168.188.112:27003
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
bean中配置的就是读写策略,包括四种:
主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:
海量数据存储问题
高并发写的问题
使用分片集群可以解决上述问题,分片集群特征:
集群中有多个master,每个master保存不同数据
每个master都可以有多个slave节点
master之间通过ping监测彼此健康状态
客户端请求可以访问集群任意节点,最终都会被转发到正确节点
IP | PORT | 角色 |
---|---|---|
192.168.188.112 | 7001 | master |
192.168.188.112 | 7002 | master |
192.168.188.112 | 7003 | master |
192.168.188.112 | 8001 | slave |
192.168.188.112 | 8002 | slave |
192.168.188.112 | 8003 | slave |
# 进入/tmp目录
cd /tmp
# 创建目录\
mkdit cluster-sharding
cd cluster-sharding
mkdir 7001 7002 7003 8001 8002 8003
port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/cluster-sharding/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /tmp/cluster-sharding/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.188.112
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /tmp/cluster-sharding/6379/run.log
# 进入/tmp目录
cd /tmp/cluster-sharding
# 执行拷贝
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
# 进入/tmp目录
cd /tmp
# 修改配置文件
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
启动
# 进入/tmp目录
cd /tmp/cluster-sharding
# 一键启动所有服务
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
ps -ef | grep redis
ps -ef | grep redis | awk '{print $2}' | xargs kill
或者printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown
redis-cli --cluster create --cluster-replicas 1 192.168.188.112:7001 192.168.188.112:7002 192.168.188.112:7003 192.168.188.112:8001 192.168.188.112:8002 192.168.188.112:8003
redis-cli -p 7001 cluster nodes
- 集群操作时,需要给redis-cli
加上-c
参数才可以:-c
:Enable cluster mode (follow -ASK and -MOVED redirections).【启用集群模式(遵循-ASK和-MOVED重定向)。】
redis-cli --cluster help
需求:向集群中添加一个新的master节点,并向其中存储 num = 666
两个新的功能:
mkdir 7004
cp redis.conf 7004
sed -i s/6379/7004/g 7004/redis.conf
redis-server 7004/redis.conf
Do you want to proceed with the proposed reshard plan (yes/no)? yes
redis-cli -p 7001 cluster nodes
redis-cli -p 7002 shutdown
利用cluster failover命令可以手动让集群中的某个master宕机,然后将master的身份切换到执行cluster failover命令的slave节点,实现无感知的数据迁移。其流程如下:
这种failover命令可以指定三种模式:
演示
步骤如下: