目录
Redis持久化
RDB持久化
AOF持久化
RDB与AOF对比
Redis主从
全量同步
增量同步
Redis哨兵
RedisTemplate集成哨兵实现
Redis分片集群
散列插槽
集群伸缩
故障转移
自动故障转移
手动故障转移
RedisTemplate访问分片集群
Redis持久化
RDB持久化
RDB全称Redis Database Backup file(Redis 数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据记录到磁盘中。当Redis实例故障重启后,会从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认保存在当前运行目录中。
RDB持久化会在以下四种情况下执行:
1. 执行save命令
save命令会让主进程执行RDB,执行期间所有其他命令都会被阻塞,该命令通常在数据迁移时才会用到。
2. 执行bgsave命令
执行bgsave命令后,系统会开启独立进程完成RDB,主进程可以持续处理用户请求,不受其影响。
3. Redis停机时
Redis停机时会自动执行一次save命令,实现RDB持久化。
4. 触发RDB条件时
Redis内部存在触发RDB的机制,可以在redis.conf文件中设置,格式如下。
# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1
save 300 10
save 60 10000
RDB的其它配置也可以在redis.conf文件中进行设置。
# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes# RDB文件名称
dbfilename dump.rdb # 文件保存的路径目录
dir ./
bgsave命令原理
在Linux系统中,所有进程都无法直接操作物理内存,只能通过页表对物理内存进行操作。而bgsave执行时会fork主进程得到子进程,同时会将主进程的页表复制到子进程的页表中,因此子进程和主进程的页表是相同的,所以主进程和子进程从页表的映射层面实现了内存共享。
于是子进程可以通过页表读取物理内存中的数据(读取的数据即主进程操作的数据),并将读取的数据存入磁盘中,替换旧的RDB文件。
当主进程接收到请求,需要对数据进行写操作时,系统会对该数据进行拷贝,主进程可以对拷贝的数据副本进行读写操作,从而避免子进程在读数据时读到脏数据。在极端情况下,如果主进程对每个数据都进行写操作,那么每个数据都会被拷贝一次,内存将会翻倍,因此我们在开发时要给Redis预留足够的存储空间。
AOF持久化
RDB与AOF对比
Redis主从
全量同步
master如何判断slave是否是第一次进行同步数据?
这里会用到两个很重要的概念:
1.Replication ld:简称replid,是数据集的标记。若master与slave的replid一致,则说明主从属于同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid。
2.offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时会记录当前同步的offset。如果slave的offset小于master的offset,则说明slave数据落后于master,需要进行更新。因此slave进行数据同步时,必须向master声明自己的replication id和offset,master才可以判断需要同步哪些数据给slave。
简述全量同步的流程
1.slave节点请求增量同步
2.master节点判断slave节点的replid,发现不一致,拒绝增量同步
3.master将完整的内存数据生成RDB,发送RDB到slave
4.slave清空本地数据,加载master的RDB
5.master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
增量同步
简述全量同步和增量同步区别?
全量同步:master将完整的内存数据生成RDB,发送RDB到slave。后续命令则记录在repl baklog,逐个发送给slave。
增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave。
什么时候执行全量同步?
1. slave节点第一次连接master节点时;
2. slave节点断开时间太久,repl_baklog中的offset已经被覆盖时。
什么时候执行增量同步?
slave节点断开又恢复,并且在repl_baklog中能找到offset时。
Redis哨兵
选举新的master
一旦出现master故障,sentinel会选择一个salve作为新的master,选择依据如下。
1. 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds*10)则会排除该slave节点
2. 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
3. 如果slave-prority一样,则判断slave节点的sffset值,越大说明数据越新,优先级越高
4.最后是判断slave节点的运行id大小,越小优先级越高。
Sentinel的三个作用是什么?
1. 监控
2. 自动故障恢复
3. 通知
Sentinel如何判断一个redis实例是否健康?
每隔1秒向master发送一次ping命令,如果超过一定时间没有响应则认为该master是主观下线,如果大多数sentinel都认为该master主观下线,则判定master客观下线。
故障恢复步骤有哪些?
1. 选定一个slave作为新的master,并令其执行slave of no one命令
2. 让其它所有节点都执行slave of 新master命令
3. 修改故障节点配置,添加slave of 新master命令
RedisTemplate集成哨兵实现
在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。以下是实现RedisTemplate集成哨兵机制的步骤。
1. 引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 在配置文件application.yml中指定redis的sentinel相关信息
spring:redis:sentinel:master: mymasternodes:- 192.168.150.101:27001- 192.168.150.101:27002- 192.168.150.101:27003
3. 在项目的启动类中,添加一个新的bean
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
这个Bean用于配置Redis主从节点的读写策略,包括以下四种:
MASTER:从主节点读取
MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
REPLICA:从slave节点读取
REPLICA _PREFERRED:优先从slave节点读取,所有的slave都不可用才读取master
Redis分片集群
散列插槽
Redis如何判断一个key应该存放在哪个实例中?
1. Redis将16384个插槽分配给不同实例
2. 根据key的有效部分计算哈希值,对16384取余
3. 余数作为插槽位置,寻找该插槽位置所在实例即可
如何将同一类数据固定保存在同一个Redis实例中?
令这一类数据使用相同的有效部分,例如key都以{typeld}为前缀
集群伸缩
需求1:将7004端口实例添加进集群中
命令如下。
redis-cli --cluster add-node 192.168.150.101:7004 192.168.150.101:7001
反馈如下图所示,7004加入了集群,并且默认是一个master节点。
但是,可以看到7004节点的插槽数量为0,因此没有任何数据可以存储到7004上。
需求2:将数据num存储到7004节点中
因为数据key不是与节点绑定,而是与插槽绑定的,因此我们需要查看num的插槽是多少。
如上图所示,num的插槽为2765,因此我们可以将0~3000的插槽从7001转移到7004,命令格式如下。
建立连接。
反馈如下。
复制7004节点id。
输入id后反馈如下。
此处询问:你的插槽是从哪里移动过来的?
all:代表全部,也就是各个节点转移一部分
具体的id:目标节点的id
done:结束输入
这里我们要从7001获取,因此填写7001的id,输入done表示结束填写。
反馈如下。
输入yes,确定转移插槽。
再次输入命令,查看节点信息。
可以看到,3000个插槽转移成功。
故障转移
自动故障转移
我们运行命令停止一个redis实例 ,模拟一个节点宕机,观察集群的反应。
redis-cli -p 7002 shutdown
1. 首先是该实例与其它实例失去连接
2. 然后是疑似宕机
3. 最后是确定下线,自动提升一个slave为新的master
4. 当7002再次启动,就会变为一个slave节点了
手动故障转移
RedisTemplate访问分片集群
RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致:
1. 引入redis的starter依赖
2. 配置分片集群地址
3. 配置读写分离
与哨兵模式相比,其中只有分片集群的配置方式略有差异,如下。
spring:redis:cluster:nodes:- 192.168.150.101:7001- 192.168.150.101:7002- 192.168.150.101:7003- 192.168.150.101:8001- 192.168.150.101:8002- 192.168.150.101:8003