🌳 性能相关

吞佛童子2022年10月10日
  • db
  • Redis
大约 3 分钟

🌳 性能相关

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. 内存不足如何处理?

  1. 修改配置文件 redis.conf 的 maxmemory 参数,或 通过命令 set maxmemory 动态设置,增加可用内存
  2. 设置合理的 内存淘汰策略,及时释放内存空间
  3. 使用 Redis 集群,横向扩容

4. Redis 阻塞如何解决?

1) 出现 慢查询

  1. 数据结构 使用不合理
  2. 使用了 复杂度高 的命令
  3. 如何处理慢查询?
    • 找到慢查询
      • 通过命令 slowlog get{n} 获取最近的 n 条慢查询命令
    • 优化慢查询
      • 数据结构调整
      • 命令优化,尽可能不使用 keys sort 等命令

2) CPU 饱和

  • Redis 通过单线程处理命令,即使某个 CPU 一直在处理命令,但是速度仍然不够
  • 优化:
    • 判断 Redis 并发量是否达到极限
      • 命令 redis-cli-h{ip}-p{port}--stat
    • 搭建 Redis 集群,分摊 请求压力
    • 排除 内存 & 指令 的使用

3) 持久化操作造成的阻塞

  1. fork 阻塞
    • 执行 RDB 生成快照
    • 执行 AOF rewrite,缩容 AOF 文件大小
    • fork 本身耗时过长,也会导致 主线程 的阻塞
  2. AOF 刷盘
    • fsync 操作当硬盘压力过大时,该操作需要等待,直到写入完成,而若规定时间内无法执行完该操作,会阻塞本线程
  3. HugePage 写操作
    • 每次写操作引起的 内存页单位由 4KB 变为 2MB

5. Redis 为什么这么快?

1) 高效的数据结构

2) 基于内存

3) 单线程

单线程

  1. 单线程避免了 线程切换 带来的开销,也不存在 并发安全 问题
  2. Server 主线程为单线程,用于处理 网络请求,进行命令的执行,并返回结果

4) IO 多路复用

  • select
  • epoll
  • kqueue
  • evport
上次编辑于: 2022/10/10 下午8:43:48
贡献者: liuxianzhishou