redis高级

1高级特性

1 过期策略

Redis 采用「惰性删除 + 定期删除」的策略:

  • 惰性删除:访问 key 时检查是否过期
  • 定期删除:周期性随机检查一部分 key 并删除

2 内存淘汰策略

当内存达到上限时,根据 maxmemory-policy 配置的策略淘汰数据:

策略 说明
noeviction 不淘汰,写操作报错(默认)
allkeys-lru 对所有 key 使用 LRU 淘汰
allkeys-lfu 对所有 key 使用 LFU 淘汰
allkeys-random 随机淘汰
volatile-lru 对设置了过期时间的 key 使用 LRU
volatile-ttl 淘汰剩余 TTL 最短的 key

3 分布式锁

# 加锁(NX 表示不存在才设置)
SET lock_key unique_value NX PX 30000

# 解锁(使用 Lua 脚本保证原子性)
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock_key unique_value

4 Pipeline(管道)

批量执行命令,减少网络往返。

import redis

r = redis.Redis(host='localhost', port=6379)
pipe = r.pipeline()
for i in range(1000):
    pipe.set(f'key{i}', i)
pipe.execute()

2. 持久化

2.1 RDB(快照)

将某个时间点的数据快照保存到磁盘。

# redis.conf 配置
save 900 1       # 900 秒内至少 1 次修改触发保存
save 300 10      # 300 秒内至少 10 次修改
save 60 10000    # 60 秒内至少 10000 次修改
dbfilename dump.rdb

优点:文件紧凑,适合备份和灾难恢复
缺点:可能丢失最后一次快照后的数据

2.2 AOF(追加文件)

记录每次写操作命令。

appendonly yes
appendfilename "appendonly.aof"
appendfsync always     # 每次写都同步,最安全但最慢
appendfsync everysec   # 每秒同步一次(默认,推荐)
appendfsync no         # 由操作系统决定

优点:数据更安全,丢失少
缺点:文件更大,恢复慢

2.3 混合持久化(推荐)

aof-use-rdb-preamble yes

3. 主从复制与哨兵

3.1 主从复制

# 从节点配置
replicaof <master-ip> <master-port>
# 查看复制状态
redis-cli info replication

3.2 哨兵(Sentinel)

监控主节点,主节点宕机时自动故障转移。

# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster password
redis-sentinel sentinel.conf

4. 集群

Redis Cluster 提供数据分片和高可用。

# 创建集群(3 主 3 从)
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

5. 性能优化与常见问题

5.1 性能优化建议

  • 使用合适的数据结构,避免大 key 和热 key
  • 使用 Pipeline 批量操作
  • 避免使用 KEYS 命令,使用 SCAN
  • 合理设置过期时间和内存淘汰策略
  • 关闭 THP(透明大页)
  • 使用连接池

5.2 常见问题

问题 原因 解决方案
缓存穿透 查询不存在的数据 布隆过滤器、缓存空值
缓存击穿 热点 key 过期瞬间大量请求 互斥锁、逻辑过期
缓存雪崩 大量 key 同时过期 过期时间加随机值
大 key 单个 key 数据过大 拆分 key

6. python语言客户端使用示例

Python

pip install redis
import redis

r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

# String
r.set('name', 'zhangsan')
print(r.get('name'))

# Hash
r.hset('user:1', mapping={'name': 'zhangsan', 'age': 20})
print(r.hgetall('user:1'))

# 过期时间
r.setex('token', 3600, 'abc123')

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容