Redis高级 —- 持久化(1)

RDB

RDB就是Redis数据快照,其将Redis的数据本身保存到硬盘

如果直接使用save来执行RDB,会阻塞所有命令

建议使用bgsave,会开启子进程来执行RDB,避免主进程收到阻塞

RDB在Redis内部的使用

redis.conf中配置了默认的RDB机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 开启RDB
# save "" 表示禁用RDB
# 3600s内,若至少有1个key被修改,则执行bgsave
save 3600 1
save 300 100
save 60 10000

# 是否压缩rdb文件
rdbcompression yes

# rdb文件名
dbfilename dump.rdb
# 文件保存的路径目录
dir ./

RDB原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

AOF

即追加文件,Redis处理的每一个写命令都会记录在AOF,可看作命令日志文件

AOF默认关闭,需要修改redis.conf配置文件来开启AOF:

1
2
3
4
# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"

AOF的命令记录的频率也可以通过redis.conf文件来配:

1
2
3
4
5
6
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

三种策略对比:

RDB与AOF对比

AOF文件重写

如果之前写入了a,然后又写入了a,会执行文件重写,将用最新的值替代之前的值

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

1
2
3
4
# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb

集群

数据同步原理

主从第一次同步数据是全量同步,从节点会从主节点中拉取所有数据bgsave(RBD)

新写的数据会使用AOF进行同步,将在RDB的时间内收到的命令在从节点中再执行一次(增量数据同步)

image-20240227141357869

数据同步情况的判断

  • Replication Id: 简称replid,是数据集的标记; slave会继承master的replid
  • offset: 偏移量,若从节点offset小于offset,则说明从节点数据落后于主节点

主节点的增量同步数据若过长时间没有存入从节点,会导致溢出的数据覆盖原有数据,这时从节点要获取主节点数据就需要获取全量数据了

这个问题无法避免,只能尽量去优化,减少其出现的概率

数据同步的优化

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

哨兵

上面的最基础的集群中,若主节点宕机了,那么整个服务就会陷入混乱; 这时就引入了哨兵Sentinel机制

哨兵负责衔接外部的请求和Redis集群,能为Redis访问提供正确的结点

服务状态监控

Sentinel的服务状态监控基于心跳机制,分为主观下线和客观下线

  • 主观下线: 某个Sentinel节点发现某实例未在规定时间内响应,则将其记为主管下线
  • 客观下线: 若超过某个数量(最好是过半哨兵)的哨兵都认为某个节点主观下线了,就将这个实例记为客观下线

选举

当发现master出现问题,就需要哨兵们选举新的master

  • 首先判断slave和master断开时间的长短,若超过指定值则会将该slave排除
  • 再判断slave的优先级,越小越高,0不参加选举
  • 再判断offset值,越大说明越新,优先级更高

故障转移

  • 哨兵给slave发送命令让该节点成为master
  • 哨兵再给其余slave发送slave of (新主节点地址),让这些slave成为新的master的从节点
  • 最后哨兵将故障的master节点标记为slave,若其在之后恢复正常了,会成为新master的从节点

哨兵集群搭建

跟搭建redis集群差不多,不赘述了

这里在搭建的时候,redis声明ip跟着文档填忘了改成自己的了,抓了一个多小时虫子…

分片集群

主从+哨兵实现了高可用高并发,但是仍然没有解决两个问题

  • 海量数据存储
  • 高并发写

使用分片集群可以结局上述问题, 分片集群的特征如下

  • 集群中有多个master, 保存不同数据
  • 每个master都有多个slave结点
  • master之间互相ping来检测状态
  • 客户端可以访问任意节点,最终会通过redis集群内部的路由转发到正确的节点

image-20240228111619707

散列插槽

Redis会把每一个节点映射到一个插槽上,数据的key不与节点绑定,而是与插槽绑定; Redis会根据key来计算插槽值,然后把对应的值放到相应的插槽中, 实际上就是一个hash

集训伸缩

Redis集群支持动态的增加或者减少实例数量