艾体宝干货|【Redis实用技巧#16】架构解析(下):持久化、Lua、内存管理与集群设计

张开发
2026/6/16 9:36:29 15 分钟阅读
艾体宝干货|【Redis实用技巧#16】架构解析(下):持久化、Lua、内存管理与集群设计
在上一篇中我们分析了 Redis 的几个核心架构单线程执行模型I/O 多路复用高效数据结构但真正让 Redis 在生产环境稳定运行的关键还包括持久化策略Lua 原子脚本内存管理Pipeline 优化Cluster 扩展这些机制决定了 Redis 在 ​高并发系统中的工程表现​。Redis 持久化机制Redis 是 ​内存数据库​。如果完全不持久化Redis restart 数据全部丢失因此 Redis 提供两种持久化方式机制类型RDB快照AOF操作日志RDB快照机制RDB 会定期生成 ​数据集快照​。配置示例save 900 1 save 300 10 save 60 10000含义条件触发900 秒内1 次写入300 秒内10 次写入60 秒内10000 次写入执行流程当触发保存Redis main process │ │ fork() ▼ Child Process → 写入 dump.rdb Parent Process → 继续服务请求关键技术Copy-On-Write写操作发生时才复制内存页隐藏问题fork 延迟如果 Redis 数据量很大dataset 10GBfork 可能需要200ms - 500ms在此期间Redis 停止响应请求这也是很多系统出现周期性延迟尖刺的原因。AOF操作日志AOF 记录所有写操作SET user:1 John INCR counter DEL keyRedis 重启时Replay log → 重建数据AOF 同步策略配置appendfsync always appendfsync everysec appendfsync no含义策略特点always最安全 最慢everysec推荐no最快一般生产环境everysec最多丢失1 秒数据AOF RewriteAOF 会不断增长。例如SET key 1 SET key 2 SET key 3其实只需要SET key 3因此 Redis 会执行 ​AOF 重写​BGREWRITEAOF生成更小的日志。Lua 脚本为什么 Redis 需要 Lua很多开发者第一次写 Redis 代码会遇到这种逻辑GET counter if counter 100 INCR counter EXPIRE counter 60问题GET 和 INCR 之间可能被其他请求插入导致限流失效Lua 解决方案Lua 脚本在 Redis 中原子执行示例local key KEYS[1]local limit tonumber(ARGV[1])local ttl tonumber(ARGV[2])local current redis.call(GET, key)if not current then current 0else current tonumber(current)endif current limit then redis.call(INCR, key) redis.call(EXPIRE, key, ttl)return 1elsereturn 0end执行EVALSHA script特点特性说明原子执行不会被打断减少 RTT一次请求服务器逻辑避免客户端协调Redis 内存管理Redis 完全运行在内存中。因此 ​内存管理极其关键​。内存限制配置maxmemory 2gb当超过限制触发 ​淘汰策略​。常见策略策略说明noeviction拒绝写入allkeys-lru淘汰最近最少使用volatile-lru淘汰带 TTL 的 keyallkeys-random随机缓存系统通常使用allkeys-lruRedis LRU 不是严格 LRU为了性能Redis 使用 ​采样算法​随机选 N 个 key 淘汰最旧的这样避免维护完整 LRU 链表。内存碎片运行一段时间后可能看到used_memory 2.5GB used_memory_rss 4.8GB碎片率1.92原因内存分配块key 删除留下空洞解决方案activedefrag yes或者定期重启 RedisPipelineRedis 性能加速很多系统 Redis 慢的原因不是 Redis 本身。而是网络 RTT例如1000 次 SET如果逐条发送1000 次 RTTPipelinePipeline pipeline jedis.pipelined() for i0..1000 pipeline.set(key,value) pipeline.sync()效果1000 请求 → 1 次 RTT性能提升10x - 100xRedis 事务的行为Redis 提供MULTI EXEC但很多人误以为它类似 SQL 事务。实际上Redis ​没有 rollback​。示例MULTI SET key1 value1 BADCOMMAND SET key2 value2 EXEC结果key1 成功 key2 成功即使中间有错误。因此复杂原子逻辑应该使用Lua Script而不是事务。Redis Cluster当单机 Redis 无法满足需求时需要水平扩展Redis Cluster 使用16384 hash slots计算CRC16(key) % 16384分布示例NodeA 0-5460 NodeB 5461-10922 NodeC 10923-16383多 Key 限制例如MGET key1 key2如果 key 在不同节点CROSSSLOT error解决方案hash tags示例{user}:1 {user}:2同一 slot。Redis 监控生产环境必须监控SLOWLOGSLOWLOG GET常见慢操作KEYS *大集合扫描INFO关键指标used_memory connected_clients evicted_keys keyspace_hits建议监控指标阈值内存80%缓存命中率95%evicted_keys0总结Redis 的成功并不是偶然。它依赖一系列 ​极度克制的架构设计​设计选择目的单线程简化并发I/O 多路复用高连接数数据结构优化高性能Lua原子逻辑Pipeline减少 RTTCluster水平扩展理解这些机制之后你会发现Redis 并不是“简单缓存”而是一套 ​高性能实时数据平台​。

更多文章