🌳 性能相关
2022年10月10日
- db
🌳 性能相关
1. 删除策略
- 过期 数据 的删除策略
1) 定期删除
- 每个一段时间,随机选取一部分数据进行 检测 & 删除
2) 惰性删除
- 在查询到该 key 的时候,若发现已经过期,则对其删除,返回 null
2. 淘汰策略
- 若内存达到限制,此时会执行 淘汰机制,确定要淘汰 哪些 key 所在的数据
- 在 64 位的系统中,Redis 是没有对内存容量做限制的,但是在 32 位系统中默认内存容量的默认值是
3GB
- 查看最大占用内存大小
config get maxmemory
- 设置最大占用内存
config set maxmemory 100mb
- 查看当前内存淘汰策略
config get maxmemory-policy
- 设置内存淘汰策略
config set maxmemory-policy allkeys-lru
#define MAXMEMORY_FLAG_LRU (1<<0)
#define MAXMEMORY_FLAG_LFU (1<<1)
#define MAXMEMORY_FLAG_ALLKEYS (1<<2)
// 1. 设置过期时间的 key 集合中,最久未使用的 key
#define MAXMEMORY_VOLATILE_LRU ((0<<8)|MAXMEMORY_FLAG_LRU)
// 2. 设置过期时间的 key 集合中,最久未使用 且 使用次数最少 的 key
#define MAXMEMORY_VOLATILE_LFU ((1<<8)|MAXMEMORY_FLAG_LFU)
// 3. 设置过期时间的 key 集合中,最先达到过期时间 的 key,若没有,则回退到 MAXMEMORY_NO_EVICTION 策略
#define MAXMEMORY_VOLATILE_TTL (2<<8)
// 4. 设置过期时间的 key 集合中,随机删除 key
#define MAXMEMORY_VOLATILE_RANDOM (3<<8)
// 5. 所有 key 集合中,最久未使用的 key
#define MAXMEMORY_ALLKEYS_LRU ((4<<8)|MAXMEMORY_FLAG_LRU|MAXMEMORY_FLAG_ALLKEYS)
// 6. 所有 key 集合中,最久未使用 且 使用次数最少 的 key
#define MAXMEMORY_ALLKEYS_LFU ((5<<8)|MAXMEMORY_FLAG_LFU|MAXMEMORY_FLAG_ALLKEYS)
// 7. 所有 key 集合中,随机删除 key
#define MAXMEMORY_ALLKEYS_RANDOM ((6<<8)|MAXMEMORY_FLAG_ALLKEYS)
// 8. 默认策略,不删除任何数据,拒绝所有写入数据并返回给客户端错误信息,只响应 读操作
#define MAXMEMORY_NO_EVICTION (7<<8)
3. 内存不足如何处理?
- 修改配置文件 redis.conf 的
maxmemory
参数,或 通过命令set maxmemory
动态设置,增加可用内存 - 设置合理的 内存淘汰策略,及时释放内存空间
- 使用 Redis 集群,横向扩容
4. Redis 阻塞如何解决?
1) 出现 慢查询
- 数据结构 使用不合理
- 使用了 复杂度高 的命令
- 如何处理慢查询?
- 找到慢查询
- 通过命令
slowlog get{n}
获取最近的 n 条慢查询命令
- 通过命令
- 优化慢查询
- 数据结构调整
- 命令优化,尽可能不使用
keys
sort
等命令
- 找到慢查询
2) CPU 饱和
- Redis 通过单线程处理命令,即使某个 CPU 一直在处理命令,但是速度仍然不够
- 优化:
- 判断 Redis 并发量是否达到极限
- 命令
redis-cli-h{ip}-p{port}--stat
- 命令
- 搭建 Redis 集群,分摊 请求压力
- 排除 内存 & 指令 的使用
- 判断 Redis 并发量是否达到极限
3) 持久化操作造成的阻塞
fork
阻塞- 执行 RDB 生成快照
- 执行 AOF rewrite,缩容 AOF 文件大小
- 若
fork
本身耗时过长,也会导致 主线程 的阻塞
- AOF 刷盘
fsync
操作当硬盘压力过大时,该操作需要等待,直到写入完成,而若规定时间内无法执行完该操作,会阻塞本线程
- HugePage 写操作
- 每次写操作引起的 内存页单位由 4KB 变为 2MB
5. Redis 为什么这么快?
1) 高效的数据结构
2) 基于内存
3) 单线程
单线程
- 单线程避免了 线程切换 带来的开销,也不存在 并发安全 问题
- Server 主线程为单线程,用于处理 网络请求,进行命令的执行,并返回结果
4) IO 多路复用
- select
- epoll
- kqueue
- evport