Redis调优实战
本课程将深入讲解性能优化的核心概念和实践应用。主要内容包括:内存优化、慢查询、Pipeline、监控。
Redis的性能优化是非常重要的功能模块,在实际开发中有广泛的应用。通过本课程的学习,你将全面掌握性能优化的使用技巧。
# 查看内存使用情况
INFO memory
# 示例输出
# Memory
used_memory:10000000
used_memory_human:9.54M
used_memory_rss:15000000
used_memory_rss_human:14.31M
used_memory_peak:20000000
used_memory_peak_human:19.07M
used_memory_peak_perc:50.00%
used_memory_overhead:1000000
used_memory_startup:500000
used_memory_dataset:8500000
used_memory_dataset_perc:85.00%
allocator_allocated:11000000
allocator_active:12000000
allocator_resident:16000000
total_system_memory:1073741824
total_system_memory_human:1.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.09
allocator_frag_bytes:1000000
allocator_rss_ratio:1.33
allocator_rss_bytes:4000000
rss_overhead_ratio:0.94
rss_overhead_bytes:-1000000
mem_fragmentation_ratio:1.50
mem_fragmentation_bytes:5000000
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
# redis.conf中的编码配置
# 哈希表使用ziplist编码的最大元素数和最大元素大小
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# 列表使用ziplist编码的最大元素数和最大元素大小
list-max-ziplist-size -2 # -2表示8kb
# 集合使用intset编码的最大整数范围
set-max-intset-entries 512
# 有序集合使用ziplist编码的最大元素数和最大元素大小
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# redis.conf中的内存限制配置
maxmemory 2gb
# 内存淘汰策略
maxmemory-policy allkeys-lru
# 每次淘汰的键数量
maxmemory-samples 5
noeviction:不淘汰,内存不足时拒绝写入allkeys-lru:从所有键中选择最近最少使用的淘汰volatile-lru:从设置了过期时间的键中选择最近最少使用的淘汰allkeys-random:从所有键中随机选择淘汰volatile-random:从设置了过期时间的键中随机选择淘汰volatile-ttl:从设置了过期时间的键中选择剩余时间最短的淘汰volatile-lfu:从设置了过期时间的键中选择最少使用频率的淘汰allkeys-lfu:从所有键中选择最少使用频率的淘汰# 开启主动内存碎片整理
activedefrag yes
# 内存碎片率阈值
active-defrag-ignore-bytes 100mb
active-defrag-threshold-lower 10
active-defrag-threshold-upper 100
active-defrag-cycle-min 25
active-defrag-cycle-max 75
# 手动触发内存碎片整理
MEMORY DOCTOR
MEMORY PURGE
# redis.conf中的慢查询配置
# 慢查询日志阈值(微秒)
slowlog-log-slower-than 10000
# 慢查询日志长度
slowlog-max-len 1000
# 实际应用:生产环境配置
slowlog-log-slower-than 5000 # 5ms
slowlog-max-len 10000 # 保存10000条
# 查看慢查询日志
SLOWLOG GET
# 查看指定数量的慢查询日志
SLOWLOG GET 10
# 查看慢查询日志长度
SLOWLOG LEN
# 重置慢查询日志
SLOWLOG RESET
# 示例输出
127.0.0.1:6379> SLOWLOG GET 2
1) 1) (integer) 100
2) (integer) 1600000000
3) (integer) 20000
4) 1) "KEYS"
2) "*"
5) "127.0.0.1:6379"
6) ""
2) 1) (integer) 99
2) (integer) 1600000000
3) (integer) 15000
4) 1) "HGETALL"
2) "user:1001"
5) "127.0.0.1:6379"
6) ""
# 分析:
# 第1个元素:慢查询日志ID
# 第2个元素:执行时间戳
# 第3个元素:执行时间(微秒)
# 第4个元素:命令和参数
# 第5个元素:客户端IP和端口
# 第6个元素:客户端名称
Pipeline是Redis提供的一种批量执行命令的机制,通过减少网络往返时间来提高性能。
# 使用echo和redis-cli的--pipe选项
$ echo -e "SET key1 value1\r\nSET key2 value2\r\nGET key1\r\nGET key2" | redis-cli --pipe
# 输出
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 4
# 解释:
# SET key1 value1 → OK
# SET key2 value2 → OK
# GET key1 → "value1"
# GET key2 → "value2"
# 总共4个回复,0个错误
# 示例:Java客户端使用Pipeline
Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();
// 批量执行命令
pipeline.set("user:1001:name", "zhangsan");
pipeline.set("user:1001:age", "25");
pipeline.hset("user:1001", "name", "zhangsan");
pipeline.hset("user:1001", "age", "25");
pipeline.lpush("user:1001:orders", "order1", "order2");
pipeline.sadd("user:1001:tags", "vip", "active");
// 执行Pipeline并获取结果
List<Object> results = pipeline.syncAndReturnAll();
// 处理结果
for (Object result : results) {
System.out.println(result);
}
// 关闭连接
jedis.close();
# 实际应用:使用Pipeline批量写入数据
# 例如:批量导入用户数据、批量更新缓存等场景
# 查看服务器信息
INFO
# 查看内存信息
INFO memory
# 查看CPU信息
INFO cpu
# 查看客户端信息
INFO clients
# 查看命令统计信息
INFO commandstats
# 查看键空间信息
INFO keyspace
# 查看复制信息
INFO replication
# 查看持久化信息
INFO persistence
# 查看集群信息
INFO cluster
# 查看服务器统计信息
INFO stats
# Redis Exporter配置示例
# 启动Redis Exporter
./redis_exporter --redis.addr=redis://localhost:6379
# Prometheus配置示例
scrape_configs:
- job_name: 'redis'
static_configs:
- targets: ['localhost:9121']
scrape_interval: 15s
# Grafana面板推荐:
# 1. Redis Overview:整体状态面板
# 2. Memory Usage:内存使用监控
# 3. Command Stats:命令执行统计
# 4. Client Connections:客户端连接监控
# 5. Keyspace Analysis:键空间分析
# Prometheus告警规则示例
- name: redis_alerts
rules:
- alert: RedisDown
expr: redis_up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Redis实例宕机"
description: "Redis实例 {{ $labels.instance }} 已宕机超过5分钟"
- alert: RedisMemoryUsageHigh
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "Redis内存使用过高"
description: "Redis实例 {{ $labels.instance }} 内存使用率超过80%"
- alert: RedisConnectionsHigh
expr: redis_connected_clients > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "Redis连接数过高"
description: "Redis实例 {{ $labels.instance }} 连接数超过1000"
- alert: RedisSlowQueries
expr: increase(redis_slowlog_length[5m]) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "Redis慢查询增多"
description: "Redis实例 {{ $labels.instance }} 5分钟内慢查询超过10个"
# redis.conf中的网络配置
# 最大客户端连接数
maxclients 10000
# TCP连接超时时间
timeout 0
# TCP keepalive
tcp-keepalive 300
# 实际应用:生产环境配置
maxclients 5000
tcp-keepalive 60
# redis.conf中的服务器配置
# 后台运行
daemonize yes
# 端口
port 6379
# 绑定地址
bind 127.0.0.1
# 日志级别
loglevel notice
# 日志文件
logfile "redis.log"
# 数据库数量
databases 16
# 实际应用:生产环境配置
daemonize yes
port 6379
bind 0.0.0.0
loglevel warning
logfile "/var/log/redis/redis.log"
databases 1
# redis.conf中的持久化配置
# RDB配置
save 900 1
save 300 10
save 60 10000
# AOF配置
aof-enabled yes
appendfsync everysec
no-appendfsync-on-rewrite yes
aof-load-truncated yes
aof-rewrite-percentage 100
aof-rewrite-min-size 64mb
# 实际应用:生产环境配置
save 3600 1
save 300 100
save 60 10000
aof-enabled yes
appendfsync everysec
no-appendfsync-on-rewrite yes
# 禁用Redis的一些无用功能
# 禁用命令重命名
# rename-command FLUSHALL ""
# rename-command FLUSHDB ""
# rename-command CONFIG ""
# 禁用自动持久化测试
stop-writes-on-bgsave-error yes
# 禁用哈希表重新哈希
# hash-max-ziplist-entries 0
# hash-max-ziplist-value 0
# 优化Redis的线程配置
# IO线程数(Redis 6.0+)
io-threads 4
io-threads-do-reads yes
# 实际应用:生产环境配置(根据CPU核心数调整)
io-threads 8
io-threads-do-reads yes
# 场景特点:高并发读写,数据量大
# 优化措施:
# 1. 使用Redis Cluster:实现水平扩展
# 2. 读写分离:主节点负责写,从节点负责读
# 3. 合理设置过期时间:避免数据无限增长
# 4. 使用Pipeline:批量执行命令,提高性能
# 5. 使用监控工具:实时监控集群状态
# 6. 定期清理过期数据:使用SCAN命令代替KEYS命令
# 应用场景:
# - 商品信息缓存
# - 用户会话管理
# - 购物车数据
# - 订单缓存
# - 库存管理
# 场景特点:高并发,数据增长快
# 优化措施:
# 1. 使用Redis Cluster:实现水平扩展
# 2. 合理设置内存限制:避免内存溢出
# 3. 使用Pipeline:批量执行命令,提高性能
# 4. 使用Lua脚本:执行复杂的游戏逻辑
# 5. 定期清理过期数据:使用SCAN命令代替KEYS命令
# 6. 监控内存使用:及时发现内存泄漏
# 应用场景:
# - 玩家数据存储
# - 游戏排行榜
# - 实时在线状态
# - 游戏内货币管理
# - 游戏会话管理
# 场景特点:高可用性,数据一致性要求高
# 优化措施:
# 1. 使用主从复制:实现高可用性
# 2. 使用哨兵模式:实现自动故障转移
# 3. 合理设置持久化策略:确保数据安全
# 4. 使用Pipeline:批量执行命令,提高性能
# 5. 使用监控工具:实时监控系统状态
# 6. 定期备份数据:确保数据可恢复
# 应用场景:
# - 交易缓存
# - 用户账户信息
# - 风控数据
# - 会话管理
# - 支付信息缓存
| 命令 | 功能说明 | 使用场景 |
|---|---|---|
| INFO | 查看服务器信息 | 监控服务器状态 |
| MEMORY DOCTOR | 内存诊断 | 分析内存使用问题 |
| MEMORY USAGE | 查看键的内存使用 | 查找大键 |
| SLOWLOG GET | 查看慢查询日志 | 分析性能问题 |
| SLOWLOG LEN | 查看慢查询日志长度 | 监控慢查询数量 |
| SLOWLOG RESET | 重置慢查询日志 | 清理慢查询日志 |
| SCAN | 渐进式遍历键 | 替代KEYS命令 |
| PIPELINE | 批量执行命令 | 提高性能 |
| EVAL | 执行Lua脚本 | 复杂原子操作 |
| EVALSHA | 执行Lua脚本(使用SHA1) | 缓存Lua脚本 |
| CONFIG GET | 获取配置参数 | 查看配置 |
| CONFIG SET | 设置配置参数 | 动态修改配置 |
| EXPIRE | 设置键的过期时间 | 自动清理数据 |
| TTL | 查看键的剩余过期时间 | 监控过期时间 |
通过本课程的学习,你应该已经掌握了Redis性能优化的核心概念和使用方法。以下是本课程的主要内容总结:
Redis性能优化是一个持续的过程,需要根据实际业务场景和数据特点进行调整。通过本课程的学习,你应该已经掌握了Redis性能优化的核心技巧,能够在实际项目中应用这些知识来提高Redis的性能和稳定性。
继续深入学习和实践,关注Redis的新版本特性和最佳实践,你将能够更好地运用Redis来构建高性能、高可用的系统。