目录
四.主从同步与对象模型
1.Redis 淘汰策略
2.Redis 如何做到 持久化
2.1 redis为什么要实现持久化
2.2fork进程的写时复制机制
2.3大Key的影响
2.4redis做持久化的方式
2.5 aof
2.6 rdb
2.7 redis 持久化方式的优缺点
3.redis里面的高可用体现在哪里?
3.1redis 主从复制
3.2Redis 哨兵模式(使用较少)
3.3Redis cluster集群(重中之重)
四.主从同步与对象模型
1.Redis 淘汰策略
Redis 淘汰策略是指当 Redis 内存使用达到上限时,为了给新数据腾出空间,决定删除哪些数据的规则 。主要有以下几种:
针对设置过期时间键(volatile)的策略
volatile - lru(Least Recently Used,最近最少使用):在设置了过期时间的键中,淘汰最久未使用的键。通过记录键的访问时间,优先删除长时间未被访问的键,适用于需要定期清理过期缓存、希望保留热门数据的场景 。比如电商网站缓存商品信息,可淘汰很久未被查看的商品缓存 。
volatile - lfu(Least Frequently Used,最少频率使用) :使用 LFU 算法,在设置了过期时间的键里,淘汰访问频率最低的键。能更好保留高频访问数据,适用于有明显访问频率差异且关注过期数据清理的场景,如新闻资讯类应用,淘汰很少被点击的新闻缓存 。
volatile - ttl:在设置了过期时间的键中,优先淘汰过期时间(TTL)最短的键,即那些最近要过期的键。适合时效性敏感数据场景,如验证码、临时会话缓存 ,可及时清理即将失效数据。
volatile - random:在设置了过期时间的键中随机选择淘汰的键。适用于不太关注数据访问频率和过期先后顺序,仅需淘汰过期数据的场景 。
针对所有键(allkeys)的策略
allkeys - lru:对所有键(无论是否设置过期时间),使用 LRU 算法淘汰最久未使用的键。广泛用于缓存场景,能确保经常被访问的热点数据留在内存中,提高缓存命中率 ,像热门游戏道具缓存。
allkeys - lfu:使用 LFU 算法淘汰所有键中访问频率最低的键。适用于缓存和内存使用情况需动态调整,且有长尾访问分布、需要识别热点数据的场景 。
allkeys - random:从所有键中随机淘汰一些键。适用于不关注数据访问频率和时效性,数据权重和重要性相对均衡的场景 。
禁止淘汰策略
no - eviction:当内存达到最大限制时,不淘汰任何数据,同时拒绝新的写入请求(包括插入和更新操作),但读请求可继续。适合对数据完整性要求极高、不允许丢失数据的关键场景 ,如金融交易记录存储,但需确保系统有足够内存 。
2.Redis 如何做到 持久化
2.1 redis为什么要实现持久化
redis属于内存型数据库
redis 的数据全部在内存中,如果突然宕机,数据就会全部丢 失,因此需要持久化来保证 Redis 的数据不会因为故障而丢失, redis 重启的时候可以重新加载持久化文件来恢复数据;
2.2fork进程的写时复制机制
fork页表复制,共用同一块物理内存
父进程对对数据修改时,触发写保护中断,从而进行物理内存的复制
子进程的页表指向旧的物理内存
父进程的页表指向新的物理内存
在发生写的操作的时候,系统才会去复制物理内存
避免物理内存的复制时间过长导致父进程长时间阻塞
2.3大Key的影响
在key value中 如果value 占用大量空间就是大key
比如v是hash,zset中存储大量元素
大 Key 会导致 Redis 性能下降、操作耗时、网络拥塞、内存占用不合理、影响持久化与数据迁移等问题,危害 Redis 稳定性和可用性。
2.4redis做持久化的方式
###### aof ######
# redis.cnf
appendonly no
appendfilename "appendonly.aof"
# aof read write invert
# appendfsync always
appendfsync everysec
# appendfsync no
# auto-aof-rewrite-percentage 为 0 则关闭 aof 复写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# yes 如果 aof 数据不完整,尽量读取最多的格式正确的数据;
# no 如果 aof 数据不完整 报错,可以通过 redis-checkaof 来修复 aof 文件;
aof-load-truncated yes
# 开启混合持久化
aof-use-rdb-preamble yes
###### rdb ######
# save ""
# save 3600 1
# save 300 100
# save 60 10000
redis通常使用aof或者rdb方式做数据的持久化
默认配置下,只开启 rdb 持久化;
2.5 aof
a ppend o nly f ileaof 日志存储的是 Redis 服务器的顺序指令序列, aof 日志只记录对内存修改的指令记录;
aof
这是 Redis 中 AOF(Append - Only - File )持久化方式的三种写回策略:
always:主线程执行写命令后,立即将 AOF 日志 fsync 到磁盘 。此策略数据安全性最高,能保证最多丢失一个写命令数据,但频繁磁盘 I/O 操作会降低 Redis 性能。
every_sec:主线程执行写命令后,将写操作写入 AOF 缓冲区,由后台线程(bio_fsync_aof )每秒执行一次 fsync 将缓冲区内容刷盘 。兼顾性能与数据安全性,最多丢失 1 秒数据,是常用策略。
no:主线程执行写命令后,将写操作写入 AOF 缓冲区,不主动触发 fsync,由操作系统决定何时将缓冲区内容刷盘 。性能最佳,但在系统崩溃或断电时,可能丢失大量数据
aof-rewrite
目的
AOF 重写(aof - rewrite)是为解决 AOF 文件过大问题。AOF 文件记录 Redis 写操作,长期积累会变得庞大,导致数据恢复速度变慢,重写可缩减其体积,提升恢复效率
工作原理
Redis 调用
fork
函数创建子进程。子进程基于当前内存中的数据状态,重新构建 AOF 文件内容。在此过程中,会去除对同一 Key 的冗余操作记录。例如,多次对同一 Key 进行修改,重写时只保留最终有效操作,减少文件大小 。在子进程进行 AOF 重写期间,主线程仍正常处理写操作。这些写操作会被记录到一个重写缓冲区。当子进程完成 AOF 重写后,主线程会将重写缓冲区中的内容追加到新生成的 AOF 文件末尾,保证数据的一致性 。
2.6 rdb
rdb
fork 子进程进行持久化:Redis 利用
fork
系统调用创建一个子进程。父进程(Redis 主进程)继续处理客户端请求,子进程负责将当前 Redis 内存中的数据快照写入磁盘。这样做的好处是主进程不会被磁盘 I/O 操作阻塞,保证 Redis 服务在持久化期间仍能对外提供服务 。
基于内存中(所有数据)对象编码直接持久化:RDB 会按照 Redis 数据在内存中的对象编码方式,直接将所有数据以二进制格式保存到磁盘文件中。比如字符串、哈希、列表等不同数据结构,都依据其在内存中的编码规则进行持久化存储 。生成的 RDB 文件紧凑,占用磁盘空间相对较小,恢复数据时速度较快,适合用于备份、灾难恢复等场景
rdb-aof混用
写操作缓冲与追加:在 RDB 持久化期间,Redis 主线程正常处理的写操作,会被记录到一个重写缓冲区。当子进程完成 RDB 文件生成后,主线程会把重写缓冲区中的内容追加到 AOF 文件末尾。这样既利用了 RDB 文件紧凑、恢复快的优势,又通过 AOF 追加后续写操作,保证数据的完整性,减少数据丢失风险
2.7 redis 持久化方式的优缺点
aof
优点:数据可靠,丢失较少,持久化过程代价比较低
缺点:aof文件过大,数据恢复慢
rdb
优点:rdb文件小,数据恢复快
缺点:数据丢失多,持久化过程代价比较高
所以我们需要采用 aof-rewrite 和 rdb-aof混用 来对持久化方式进行优化
3.redis里面的高可用体现在哪里?
3.1redis 主从复制
主要用来实现 redis 数据的可靠性;防止主 redis 所在磁盘损坏,造成数据永久丢失;主从之间采用异步复制的方式;

异步复制
全量数据同步:从节点(replica)初次连接主节点(master)或与主节点断开连接后重新连接时,会进行全量数据同步。主节点将自身的所有数据发送给从节点,从节点接收并加载这些数据,以此来和主节点数据保持一致 。
增量数据同步:在全量同步完成后,主节点后续产生的写操作会以增量形式发送给从节点。主节点将写命令发送给从节点执行,使从节点数据能随着主节点变化而更新 。
可能带来数据不一致:由于异步复制中,主节点执行写操作后无需等待从节点确认就继续处理其他请求,若主节点在向从节点发送增量数据前发生故障,就可能导致部分从节点数据和主节点不一致 。
环形缓冲区、复制偏移量
环形缓冲区:主节点会维护一个环形缓冲区来记录写操作命令。它是一个固定大小的缓冲区,新的写操作命令会覆盖最早的命令(当缓冲区满时 )。环形缓冲区为从节点增量同步提供数据来源 。
复制偏移量:主从节点都会维护一个复制偏移量。主节点每执行一个写操作,偏移量就会增加;从节点接收并执行主节点发送的写操作后,也会更新自己的偏移量。复制偏移量用于标识数据同步的位置,在网络故障等情况恢复后,从节点可依据偏移量与主节点进行数据同步 。
runid
runid 是 Redis 实例启动时生成的唯一随机 ID 。在主从复制中,主节点的 runid 会发送给从节点,从节点将其保存,用于标识主从映射关系。当从节点与主节点重新连接时,会通过 runid 确认是否还是原来的主节点 。
主从复制作用
单点故障:主从复制可以在一定程度上解决单点故障问题。当主节点出现故障时,可将从节点提升为主节点继续提供服务,减少服务中断时间 。
可用性的基础:主从复制为 Redis 服务的可用性提供了基础保障。从节点可以分担读请求,提高系统的并发处理能力;同时在主节点故障时可切换,保证服务的连续性 。
注意事项
建立连接:replica 必须主动向 master 建立连接,否则无法新增 replica 。这是因为 Redis 的主从复制机制设计为从节点主动发起连接请求,主节点被动接受连接并提供数据同步 。
拉取数据:replica 主动向 master 拉取数据。在网络出现问题后,replica 保存有同步位置(通过复制偏移量 ),当网络恢复时,可依据该位置继续从 master 拉取数据,实现断点续传式的数据同步 。
replica主动向master建立连接并从中拉取数据
3.2Redis 哨兵模式(使用较少)
哨兵模式是 Redis 可用性的解决方案;它由一个或多个 sentinel实例构成 sentinel 系统;该系统可以监视任意多个主库以及这些主库所属的从库;当主库处于下线状态,自动将该主库所属的某个从库升级为新的主库;客户端来连接集群时,会首先连接 sentinel ,通过 sentinel 来查询主节点的地址,并且通过 subscribe 监听主节点切换,然后再连接主节点进行数据交互。当主节点发生故障时, sentinel 主动推送新的主库地址。通过这样客户端无须重启即可自动完成节点切换。哨兵模式当中涉及多个选举流程采用的是 Raft 算法的领头选举方法的实现;
哨兵模式流程
主观下线:哨兵节点会定期向主节点和从节点发送心跳检测命令。如果在规定时间内未收到主节点的响应,该哨兵节点会将主节点标记为 “主观下线”,即从自身视角判断主节点出现问题 。
客观下线:当一个哨兵节点将主节点标记为主观下线后,它会与其他哨兵节点进行通信,交换对主节点状态的判断。当判断主节点下线的哨兵节点数量达到一定阈值(配置文件中设定 ),就会将主节点标记为 “客观下线”,即大家公认主节点已无法正常工作 。
哨兵选举:在确认主节点客观下线后,哨兵节点之间会进行选举,选出一个 “领导者” 哨兵节点。选举一般基于 Raft 算法等分布式选举算法,获得多数投票的哨兵节点成为领导者 。
从库选主:当选出的领导者哨兵节点会从可用的从节点中挑选一个来晋升为主节点。挑选依据包括从节点的优先级(可在配置文件中设置 )、复制偏移量(偏移量越大表示数据越新 )等因素 。
故障转移:确定新主节点后,领导者哨兵节点会指挥其他从节点去连接新主节点,并开始从新主节点进行数据复制。同时,会将原主节点标记为已下线,当它恢复后将作为新主节点的从节点 。
如何使用
连接哨兵节点:客户端首先需要连接到一个或多个哨兵节点,获取关于主从节点的相关信息 。
获取主节点地址,并连接:客户端从哨兵节点处获取当前主节点的地址信息,然后直接连接到主节点进行数据读写操作 。
发起发布订阅连接,监听主节点迁移信息:客户端与哨兵节点建立发布订阅连接,以便在主节点发生故障转移、迁移时,能够及时收到通知,更新连接的主节点地址 。
缺点
部署麻烦:相比简单的主从复制模式,哨兵模式需要部署多个哨兵节点,涉及节点配置、网络配置等多方面工作,增加了运维成本和复杂度 。
没有避免数据丢失问题:在主节点发生故障时,若部分从节点还未完全同步主节点数据,故障转移后可能导致这部分数据丢失 。比如异步复制场景下,主节点新写的数据还没来得及同步给从节点就故障了 。
没有数据扩展机制:哨兵模式主要解决的是主节点高可用问题,并没有提供数据分片、扩展存储容量等机制,当数据量增长时难以满足需求 。
几十秒:这里可能指故障转移的时间,一般在几十秒左右。虽然能实现自动故障转移,但几十秒的服务中断时间在一些对可用性要求极高的场景下可能无法接受
3.3Redis cluster集群(重中之重)
Redis cluster 将所有数据划分为 16384 个槽位,每个 redis 节点负责其中一部分槽位。 cluster 集群是一种 去中心化 的 集群方式;
如图,该集群由三个 redis 节点组成,每个节点负责整个集群的一部分数据,每个节点负责的数据多少可能不一样。这三个 节点 相互连接组成一个 对等的集群 ,它们之间通过一种特殊的二
进制协议交互集群信息;当 redis cluster 的客户端来连接集群时,会得到一份集群的槽位配置信息。这样当客户端要查找某个 key 时,可以直接定位到目标节点。客户端为了可以 直接定位 (对 key 通过 crc16 进行 hash 再对2的14次方取余)某个具体的 key 所在节点,需要缓存槽位相关信息,这样才可以准确快速地定位到相应的节点。同时因为可能会存在客户端与服务器存储槽位的信息不一致的情况,还需要 纠正机制 (通过返回 - MOVED 3999 127.0.0.1:6479 ,客户端收到后需要立即纠正本地的槽位映射表)来实现槽位信息的校验调整。另外, redis cluster 的每个节点会将集群的配置信息持久化到配置文件中,这就要求确保配置文件是可写的,而且尽量不要依靠人工修改配置文件;下图来源于网络;尽量使三个主节点的数据均衡;分布式一致性 hash
集群配置
创建六个文件夹分别为7001 7002 7003 7004 7005 7006
每个文件夹里面的.conf文件内容设置如下 编号对标即可
设置start.sh文件并授权
启动start.sh文件
智能创建集群
主:7001 从:7006
主:7002 从:7004
主:7003 从:7005
配置成功
测试
补充:
主节点如果宕机 从节点会替换过去
Redis 集群中主节点宕机后,从节点经故障检测与选举成为新主节点,丢弃旧缓存、更新集群状态,通过持久化恢复及后续复制同步数据,保障数据一致性,也可手动触发从节点替换主节点。