今天是2025/04/01 20:13 day 16
总路线请移步主页Java大纲相关文章
今天进行Redis 3,4,5 个模块的归纳
首先是Redis的相关内容概括的思维导图
3. 持久化机制(深度解析)
3.1 RDB(快照)
-
核心机制:
-
触发条件:
-
手动触发:
SAVE
(阻塞主线程)或BGSAVE
(后台fork子进程生成快照)。 -
自动触发:根据配置规则(如
save 900 1
表示900秒内至少1次修改)。
-
-
文件生成:生成二进制文件
dump.rdb
,包含某一时刻的数据全集。 -
内存优化:子进程通过写时复制(Copy-On-Write)技术避免全量内存拷贝。
-
-
优缺点:
-
优点:
-
文件紧凑,恢复速度快。
-
适合冷备和灾难恢复。
-
-
缺点:
-
可能丢失最后一次快照后的数据(取决于触发频率)。
-
大数据量时
BGSAVE
的fork操作可能阻塞主线程(内存越大阻塞时间越长)。
-
-
-
配置优化:
# redis.conf dbfilename dump.rdb # RDB文件名 dir /var/lib/redis # 存储路径 stop-writes-on-bgsave-error yes # 磁盘满时禁止写入 rdbcompression yes # 启用压缩
3.2 AOF(追加日志)
-
核心机制:
-
日志记录:以文本格式记录所有写操作命令(如
SET
、HSET
)。 -
重写机制:通过
BGREWRITEAOF
压缩日志,删除冗余命令(如多次INCR
合并为最终值)。 -
同步策略:
-
appendfsync always
:每次写操作同步到磁盘(数据最安全,性能最低)。 -
appendfsync everysec
:每秒同步(默认,平衡安全与性能)。 -
appendfsync no
:由操作系统决定(性能最高,可能丢失最多数据)。
-
-
-
优缺点:
-
优点:数据丢失风险低(最多丢失1秒数据)。
-
缺点:
-
文件体积大,恢复速度慢。
-
频繁写入可能影响性能(尤其是
always
模式)。
-
-
-
配置优化:
# redis.conf appendonly yes # 启用AOF appendfilename "appendonly.aof" auto-aof-rewrite-percentage 100 # 文件增长100%后触发重写 auto-aof-rewrite-min-size 64mb # 最小重写文件大小
3.3 混合持久化(Redis 4.0+)
-
工作机制:
-
快照数据(RDB格式) + 增量AOF日志,保存在同一个AOF文件中。
-
重启时先加载RDB快照,再重放后续AOF命令。
-
-
优势:
-
结合RDB的快速恢复和AOF的低数据丢失风险。
-
AOF文件可读性增强(RDB头部 + 文本日志)。
-
-
启用方式:
aof-use-rdb-preamble yes # 在redis.conf中配置
4. 高可用与集群(深度解析)
4.1 主从复制
-
核心流程:
-
全量同步:
-
Slave发送
PSYNC
命令请求同步。 -
Master fork子进程生成RDB文件并发送给Slave。
-
Slave清空旧数据,加载RDB文件。
-
增量同步:
-
Master将后续写命令存入复制缓冲区(Replication Buffer)。
-
Slave持续接收并执行缓冲区中的命令。
-
-
配置示例:
# Slave节点配置 replicaof 192.168.1.100 6379 # 指定Master地址 replica-read-only yes # Slave只读
-
常见问题:
-
复制延迟:网络波动或Master写入量过大导致缓冲区溢出(需监控
repl_backlog
)。 -
脑裂问题:网络分区时出现多个Master(需结合哨兵解决)。
-
4.2 哨兵(Sentinel)
-
核心功能:
-
监控:定期检查Master/Slave健康状态。
-
故障转移:Master宕机时,自动选举新Master。
-
通知:通过Pub/Sub频道向客户端发送故障事件。
-
-
选举机制:
-
Sentinel通过Raft协议选举Leader。
-
Leader Sentinel从Slave中选出新Master(优先级 + 复制偏移量)。
-
-
配置示例:
# sentinel.conf sentinel monitor mymaster 192.168.1.100 6379 2 # 监控名为mymaster的集群,2表示至少2个Sentinel同意故障判定 sentinel down-after-milliseconds mymaster 5000 # 5秒无响应判定为宕机 sentinel failover-timeout mymaster 60000 # 故障转移超时时间
4.3 Cluster集群
-
数据分片:
-
哈希槽分配:16384个槽,通过
CRC16(key) % 16384
计算所属槽位。 -
节点管理:每个节点负责部分槽位,支持动态迁移(
CLUSTER ADDSLOTS
)。
-
-
节点通信:
-
Gossip协议:节点间交换槽位、状态信息,最终一致性。
-
重定向机制:客户端访问错误节点时,返回
MOVED
或ASK
错误引导重试。
-
-
故障转移:
-
从节点通过选举升级为主节点(类似哨兵机制)。
-
集群需至少包含3主3从以保证高可用。
-
-
操作命令:
CLUSTER NODES # 查看集群节点信息 CLUSTER FAILOVER [FORCE] # 手动触发故障转移 CLUSTER RESET HARD/SOFT # 重置集群节点
5. 事务与Lua脚本(深度解析)
5.1 事务
-
执行流程:
-
MULTI
开启事务。 -
缓存命令(命令不会立即执行)。
-
EXEC
提交事务(原子性执行所有命令)。 -
DISCARD
取消事务。
-
-
特性与限制:
-
非原子性:单条命令原子执行,但事务可能部分失败(如语法错误)。
-
无回滚机制:需开发者自行处理错误(如通过
WATCH
实现乐观锁)。
-
-
乐观锁示例:
WATCH balance # 监控balance键 MULTI DECRBY balance 100 # 扣减余额 EXEC # 如果balance被其他客户端修改,此处返回nil
5.2 Lua脚本
-
核心优势:
-
原子性:脚本执行期间不会被其他命令打断。
-
减少网络开销:复杂逻辑单次提交,避免多次RTT(Round-Trip Time)。
-
-
典型场景:
-
分布式锁续期:
-- KEYS[1]=锁名称,ARGV[1]=线程标识,ARGV[2]=过期时间 if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("EXPIRE", KEYS[1], ARGV[2]) else return 0 end
-
限流算法(令牌桶):
-- KEYS[1]=限流key,ARGV[1]=令牌容量,ARGV[2]=填充速率(秒) local tokens = tonumber(redis.call("HGET", KEYS[1], "tokens") or ARGV[1]) local last_time = tonumber(redis.call("HGET", KEYS[1], "last_time") or os.time()) local now = os.time() local new_tokens = math.min(ARGV[1], tokens + (now - last_time) * ARGV[2]) if new_tokens < 1 then return 0 # 无可用令牌 else redis.call("HSET", KEYS[1], "tokens", new_tokens - 1) redis.call("HSET", KEYS[1], "last_time", now) return 1 end
-
-
注意事项:
-
脚本复杂度:避免长耗时操作(如
KEYS
命令),防止阻塞主线程。 -
沙盒安全:Lua脚本无法直接调用系统命令或文件操作。
-