Redis采用自行设计的RESP(Redis Serialization Protocol)协议进行客户端与服务端通信。这个二进制安全的文本协议看似简单,却蕴含着高效的设计哲学。
协议包含五种基本类型:
实际抓包示例:
code复制*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n
对应命令:SET mykey myvalue
bash复制# 未使用管道
$ time redis-cli SET k1 v1 >/dev/null
$ time redis-cli SET k2 v2 >/dev/null
# 使用管道
$ printf "*3\r\n$3\r\nSET\r\n$2\r\nk1\r\n$2\r\nv1\r\n*3\r\n$3\r\nSET\r\n$2\r\nk2\r\n$2\r\nv2\r\n" | nc localhost 6379
实测管道技术可提升5-10倍吞吐量
python复制# 低效方式
for i in range(1000):
r.set(f'key{i}', f'value{i}')
# 高效方式
pipe = r.pipeline()
for i in range(1000):
pipe.set(f'key{i}', f'value{i}')
pipe.execute()
注意:管道中的命令是原子性执行,但非事务性。如需事务保障应使用MULTI/EXEC
Redis采用jemalloc作为默认内存分配器,其优势在于:
通过INFO memory可查看:
code复制used_memory: 1048576
used_memory_human: 1.00M
mem_fragmentation_ratio: 1.25
Redis的存储结构经过精心设计:
示例配置:
code复制hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
Redis提供8种淘汰策略:
配置方式:
code复制maxmemory 1gb
maxmemory-policy allkeys-lru
关键指标监控:当used_memory接近maxmemory时,需要及时扩容或优化
执行SAVE命令时:
解决方案:
AOF重写时同样会fork进程,优化建议:
code复制auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-rewrite-incremental-fsync yes
通过以下命令主动整理:
code复制MEMORY PURGE # jemalloc专用
CONFIG SET activedefrag yes
监控指标:
code复制mem_fragmentation_ratio > 1.5 # 需要关注
mem_fragmentation_ratio > 2.0 # 必须处理
使用redis-cli --bigkeys扫描:
code复制$ redis-cli --bigkeys
# Scanning the entire keyspace to find biggest keys
# Key with biggest string so far: 'user:1000:profile' with 102400 bytes
# Key with biggest list so far: 'task:queue' with 50000 items
处理方案:
Java客户端配置示例:
java复制JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100); // 最大连接数
config.setMaxIdle(20); // 最大空闲连接
config.setMinIdle(5); // 最小空闲连接
config.setMaxWaitMillis(3000); // 获取连接超时时间
排查步骤:
优化方案:
code复制CONFIG SET slowlog-log-slower-than 10000
SLOWLOG GET 10
解决方案:
code复制redis-cli -h node1 INFO memory | grep used_memory
Redis内部维护常见整数的共享对象(0-9999):
code复制set a 100
set b 100
# a和b实际指向同一内存地址
使用适当编码:
bash复制# 44字节以下使用embstr
SET small "12345678901234567890123456789012345678901234"
# 45字节使用raw
SET large "123456789012345678901234567890123456789012345"
统计UV场景:
code复制PFADD uv:20230501 user1 user2 user3
PFCOUNT uv:20230501
内存占用仅12KB,误差率0.81%
压测示例:
code复制redis-benchmark -t set,get -n 100000 -q -P 16 -c 50
参数说明:
python复制import redis
r = redis.Redis()
for i in range(1000000):
r.set(f'key{i}', 'x'*1024) # 1KB值
code复制watch -n 1 "redis-cli INFO memory | grep used_memory_human"
在实际生产环境中,我们发现合理配置maxmemory和淘汰策略可以避免90%的内存问题。对于热点数据,采用LFU策略通常比LRU获得更好的命中率。建议每月定期执行MEMORY STATS分析,提前发现潜在风险。