Redis中间件(四):主从同步与对象模型

发布于:2025-08-08 ⋅ 阅读:(13) ⋅ 点赞:(0)


一、淘汰策略

0. 技术背景

当redis管理的内存达到上限时,此时继续往数据库增加数据,会触发淘汰策略选择性淘汰老的数据。默认策略是禁止淘汰(redis返回错误码给server端)

  • 淘汰策略:
    LRU最近最长时间未使用、
    LFU 最近最少使用次数
    请添加图片描述

1. 过期指令(整个kv对淘汰)

//设置 key 在 seconds 秒后过期
expire [key] [time秒]  
//设置 key 在 milliseconds 毫秒后过期
pexpire [key] [time毫秒] 

//查看 key 剩余过期时间
TTL key /  PTTL  key 
//移除 key 的过期时间,使其永久存在
PERSIST  key	

实操

请添加图片描述


2. 配置maxmemory

  • maxmemory:设置Redis最大可用内存限制

    //单位支持: bytes,kb,mb,gb
    eg: maxmemory 4gb
    
  • maxmemory-policy

      策略	                  	含义
    noeviction		 不删除任何数据,写操作会报错
    allkeys-lru		 所有 key 中,淘汰最近最少使用的 key
    volatile-lru	 仅在设置了过期时间的 key 中,淘汰最近最少使用的
    allkeys-random	 所有 key 中,随机选择 key 进行淘汰
    volatile-random	 仅在设置了过期时间的 key 中,随机淘汰
    allkeys-lfu		 所有 key 中,淘汰使用频率最低的 key
    volatile-lfu	 仅在设置了过期时间的 key 中,淘汰使用频率最低的
    volatile-ttl	 仅在设置了过期时间的 key 中,淘汰即将过期的 key
    

    :volatile 策略只作用于设置了过期时间的键;
    allkeys 策略作用于所有的键;

  • maxmemory-samples
    在执行策略时,从样本中采样,然后从中选出最符合淘汰机制的key

    eg: 
    1.设置allkeys-lru,
    2.并设定 maxmemory-samples 10
    ----------------------------
    Redis会从所有key中随机采样10个,
    然后选出最近最少访问的那个key来淘汰;
    

二、持久化

1. 技术背景

redis的数据全部在内存中,如果突然宕机,数据就会全部丢失;因此需要持久化来保证Redis的数据不会因为故障而丢失,redis重启的时候可以重新加载持久化文件来恢复数据

内存化数据读取到磁盘,重启时从磁盘读回,保持数据持久化


八股1:fopen\fwrite流程

  • 机器断电 1、2数据丢失
    打开某个文件,进程关闭 1数据丢失
    请添加图片描述

八股2:fork调用- 写时复制原理

  • 为了提高效率而采用的一种延迟复制优化策略
    fork进程那一刻 相当于给父进程的内存打了一个快照
    请添加图片描述
    父子进程最初共享同一块物理内存,只有当任一方尝试修改内存时,发生写操作,才会复制对应页到新的物理内存,从而实现真正的“独立”
    请添加图片描述
    父进程对数据修改,触发写保护中断,从而进行物理内存的复制,父进程的页表指向新的物理内存(谁修改谁指向新的物理内存)

2. redis持久化方式(aof | rdb)

aof(Apped Only File)

AOF持久化通过记录服务器所执行的所有写操作命令来记录数据库状态。这些命令会被追加到AOF文件的末尾,支持:

  • always:每次写命令都会同步(sync)写入到磁盘
  • everysec:每秒将aof缓冲区内容同步到磁盘中(由后台线程执行,是默认的方式)
  • no:Redis只负责写入aof 缓存,不主动同步到磁盘,由系统决定同步或手动同步

优点: 数据更安全; 命令可读,易于恢复/调试
缺点: 文件体积大,性能开销高于rdb; 数据存在一定冗余


aof-rewrite

处理 aof 文件过大,减少 aof 数据恢复速度过慢;
防止 AOF 文件无限膨胀,是后台异步进行的,不阻塞主线程;

工作原理
fork进程,根据内存数据生成 aof 文件,避免同一个 key 历史冗余,在重写 aof 期间,对 redis 的写操作记录到重写缓存区,当重写 aof 结束后,附加到 aof 文件末尾。


rdb(Redis DataBase)

  • 周期性将内存数据写入磁盘(.rdb 文件)
  • 通过 fork 子进程来执行,不影响主线程
  • rdb 存储的是经过压缩的二进制数据

优点: 文件小,恢复速度快; 适合备份、冷存储等场景
缺点: 有数据丢失风险(最近一次快照之后的修改会丢)


rdb-aof 混用

通过 fork 子进程,根据内存数据生成 rdb 文件,在rdb持久化期间,对redis 的写操作记录到重写缓冲区,当rdb 持久化结束后,附加到 aof 文件末尾
在这里插入图片描述

大Key对持久化的影响

大Key是指单个 key 对应的数据量非常大, 会导致重启时间变长,甚至服务阻塞.

  • 对rdb:fork 期间,写时复制(COW)会导致 内存急剧增长
  • 对aof:每次修改都写入完整命令,大key会让文件迅速膨胀,AOF重写成本高

  • 两者持久化方案的优缺点对比【00:41:00】
    aof (根据写请求记录当前内存数据,有3个策略,数据冗余aof-rewrite)
    rdb(基于内存所有数据对象编码直接持久化)
    请添加图片描述
  • 配置
    #Redis 的配置主要通过 redis.conf 文件来完成
    
    #在 redis.conf 中找到以下配置项:
    appendonly yes        # 开启 AOF 持久化
    appendfsync always    # 每次写入都 fsync(最安全但性能最低)
    # appendfsync everysec # 每秒 fsync 一次(默认值,推荐)
    # appendfsync no       # 不主动 fsync,依赖系统调度(性能好,安全性低)
    
    #AOF 重写相关配置:
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    #意思是:当 AOF 文件大小是上一次 rewrite 后的 100%,且超过 64MB,就会自动触发重写(即瘦身优化)
    
    #RDB 持久化配置:
    save 900 1     # 900 秒内有 1 个 key 改变就触发快照
    save 300 10    # 300 秒内有 10 个 key 改变就触发快照
    save 60 10000  # 60 秒内有 10000 个 key 改变就触发快照
    
    # 若不需要 RDB 持久化可注释所有 save 行
    # stop-writes-on-bgsave-error yes  # RDB 异常时是否停止写入
    
    # 过期策略配置(maxmemory-policy)
    maxmemory 256mb                     # 设置内存上限,建议结合使用
    maxmemory-policy allkeys-lru       # 淘汰策略(默认是 noeviction)
    maxmemory-samples 5                # 随机选择几个 key 进行淘汰评估
    
    #启动 Redis 并应用配置
    redis-server /etc/redis/redis.conf
    
    

三、高可用

1. redis主从复制(解决单点故障)

主要用来实现redis数据的可靠性;防止主redis所在磁盘损坏,造成数据永久丢失;主从之间采用异步复制的方式(从数据库 主动向 主数据库建立连接)

  • 异步复制:主节点将写操作同步到从节点,但不是实时同步(存在数据延迟)
  • 环形缓冲区:主节点维护一个固定大小的缓冲区保存最近的写命令,用于断线后快速增量同步
  • 复制偏移量:主从节点维护一个偏移量,表示同步的数据位置,用于比对是否需要全量(主从节点之间的数据全部重新同步的过程)或增量复制(主从节点之间同步断开期间 丢失的数据部分补充同步,无需全量)
  • runid:每个 Redis 实例有唯一运行 ID,复制过程中标识主节点身份

作用: 解决了单点故障、高可用性的基础
数据同步: 全量数据同步 、 增量数据同步


2. redis哨兵模式(实现故障自动转移)

目的:实现 Redis 故障自动转移。仅仅保障了单节点的高可用(主节点宕机可自动切换,从节点提升为主)
请添加图片描述
原理图(知道怎么做可用性即可),缺点是不能进行横向扩展
请添加图片描述

[流程]
	主观下线:
	客观下线
	烧饼选举
	从库选主
	故障转移
-----------------------
[如何使用]
一个 Redis 哨兵(Sentinel)模式的配置与使用示例,包含:
	1 个主节点(master)
	2 个从节点(slave)
	3 个哨兵(sentinel)
	1 个客户端访问配置方式
------------------------
[缺点]
主观宕机存在误判风险
部署麻烦
没有避免数据丢失问题
没有数据扩展

1.主从配置

#主节点 redis-master.conf(6379)
port 6379
dir /data/redis/master
appendonly yes
 
#从节点 redis-slave1.conf(6380)
port 6380
dir /data/redis/slave1
replicaof 127.0.0.1 6379
appendonly yes
 
#从节点 redis-slave2.conf(6381)
port 6381
dir /data/redis/slave2
replicaof 127.0.0.1 6379
appendonly yes

2.哨兵配置(sentinel.conf)
每个哨兵配置几乎一样,只需修改端口和自身 IP

#哨兵1 sentinel1.conf(26379)
port 26379
dir /data/redis/sentinel1
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1

#其他两个哨兵只改端口和目录,比如:
sentinel2.conf: 端口 26380,目录 /data/redis/sentinel2
sentinel3.conf: 端口 26381,目录 /data/redis/sentinel3

3.启动
放到一个文件比如start下面,然后chmod +x,最后./start

# 启动主从
redis-server redis-master.conf
redis-server redis-slave1.conf
redis-server redis-slave2.conf
 
# 启动哨兵
redis-sentinel sentinel1.conf
redis-sentinel sentinel2.conf
redis-sentinel sentinel3.conf

3. cluster集群(去中心化)

请添加图片描述
去中心化结构,每个节点互相通信,无集中式主控节点
请添加图片描述

[特征]
1.客户端与服务端缓存槽位信息,以服务器为主,客户节点缓存主要为了避免连接切换
2.自动分片,16384(2^14)个哈希槽分配给不同节点
3.每个主节点可挂载一个或多个从节点实现高可用
--------------------------------
[流程]
1.客户端根据 key 计算哈希槽值
2.连接对应槽所属的主节点
3.若节点不对,返回 MOVED 重定向信息,客户端重新连接目标节点
--------------------------------
[缺点]
1.不支持多 key 操作跨槽执行(除非通过 hash tags)
2.集群节点间通讯复杂,部署维护成本高
3.客户端需支持 Redis Cluster 协议
  • 实操集群配置【01:38:00】
    跟视频实操一遍
    请添加图片描述
#安装redis
#hiredis-cluster 安装编译

#准备节点目录
mkdir -p ~/redis-cluster/{7000,7001,7002,7003,7004,7005}

#配置每个节点的 redis.conf
for port in 7000 7001 7002 7003 7004 7005
do
  cp /etc/redis/redis.conf ~/redis-cluster/$port/
done
#修改配置文件(每个节点都需要):以 7000 为例:~/redis-cluster/7000/redis.conf
port 7000
bind 127.0.0.1
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
dir ./
logfile "redis.log"

#启动所有 Redis 实例
for port in 7000 7001 7002 7003 7004 7005
do
  redis-server ~/redis-cluster/$port/redis.conf
done
#查看是否启动:
ps -ef | grep redis

#redis-cli创建集群
redis-cli --cluster create \
127.0.0.1:7000 \
127.0.0.1:7001 \
127.0.0.1:7002 \
127.0.0.1:7003 \
127.0.0.1:7004 \
127.0.0.1:7005 \
--cluster-replicas 1

#验证创建集群是否成功
redis-cli -c -p 7000
> cluster info
> cluster nodes

优秀笔记:
1. 主从同步与对象模型
2. Redis 主从同步与对象模型(四)
参考学习:https://github.com/0voice


网站公告

今日签到

点亮在社区的每一天
去签到