Redis 最佳实践

序言

  此文章待重构排版。

优雅的key结构

  Redis 的 Key 虽然可以自定义,但最好遵循下面的几个最佳实践约定:

  • 遵循基本格式: [业务名称]:[数据名]:[id]
  • 长度不超过44字节
  • 不包含特殊字符

优点:

  • ① 可读性强
  • ② 避免key冲突
  • ③ 方便管理
  • 更节省内存:虽然 key 是 string 类型, 但其底层编码包含 int、embt 和 raw 三种。embst 在小于 44 字节使用,采用连续内存空间,内存占用更小

BigKey

  在使用 Redis 时,常常会听到 BigKey 这个名词,那么,什么是 BigKey?为什么尽量需要避免使用 BigKey 呢?又怎么去发现 BigKey 呢?

简介

  简单来说,BigKey 通常以 Key 的大小和 Key 中成员的数量来综合判定,例如:

  • Key 本身的数据量过大: 一个 String 类型的 Key,它的值为 5 MB
  • Key 中的成员数过多: 一个 ZSET 类型的 Key, 它的成员数量为 10000 个
  • Key 中成员的数据量过大: 一个 Hash 类型的 Key, 它的成员数量虽然只有 1000 个,但这些成员的Value(值)总大小为 100 MB

  推荐值:

  • 单个 key 的 value 小于 10KB
  • 对于集合类型的 key,建议元素数量小于 1000

危害

  • 网络阻塞:对 BigKey 执行读请求时,少量的 QPS 就可能导致带宽使用率被占满,导致Redis实例,乃至所在物理机变慢
  • 数据倾斜:若 BigKey 所在的 Redis 节点内存使用率远超其他实例,无法使数据分片的内存资源达到均衡
  • 线程阻塞:对元素较多的 hash、list、zset 类型等做运算会耗时较久,使主线程被阻塞
  • CPU 压力:对 BigKey 的数据序列化和反序列化会导致 CPU 的使用率飙升,影响 Redis 节点和本机其它应用

如何发现 BigKey?

redis-cli –bigkeys

  利用redis-cli提供的--bigkeys参数, 可以遍历分析所有key,并返回 Key 的整体统计信息与每个数据的 Top1 的 bigkey。

  缺点是信息不够完整。

scan 扫描

  自己编程, 利用 scan 扫描 Redis 中的所有 key, 利用 strlen、hlen 等命令判断key的长度 (此处不建议使用 MEMORY USAGE)

第三方工具

  利用第三方工具,如 Redis-Rdb-Tools、rdb_bigkeys 分析 RDB 快照文件, 全面分析内存使用情况。

网络监控

  自定义工具, 监控进出Redis的网络数据, 超出预警值时主动告警。

如何删除 BigKey

  BigKey 内存占用较多,即便时删除这样的 key 也需要耗费很长时间,导致 Redis 主线程阻塞,引发一系列问题。

  另外,需要事先评估删除是否对生产业务存在比较大的影响,否则不建议操作。

Redis 3.0 及以下版本

  如果是集合类型,则遍历 BigKey 的元素,先逐个删除子元素,最后删除 BigKey

Redis 4.0 以后

  Redis 在 4.0 后提供了异步删除的命令:unlink

如何选择恰当的数据类型?

  例1:比如存储一个 User 对象,我们有三种存储方式:

  • ① 直接存储 JSON 字符串
    • 优点:实现简单粗暴
    • 缺点:数据耦合,不够灵活
  • ② 将字段打散再存储
    • 优点:可以灵活访问对象任意字段
    • 缺点:占用空间大、没办法做统一控制
  • ③ 使用 hash 结构存储
    • 优点:底层使用zipist,空间占用小,可以灵活访问对象的任意字段
    • 缺点:代码相对复杂

  例2:假如有 hash 类型的 key,其中有 100 万对 field 和 value, field 是自增 id,这个 key 存在什么问题?如何优化?

慢查询

  慢查询:在 Redis 执行时耗时超过某个阈值的命令,称为慢查询。

查看

  查看慢查询日志相关命令:

  • slowlog len: 查询慢查询日志长度
  • slowlog get [n]:读取 n 条慢查询日志
  • slowlog reset: 清空慢查询列表

优化

  慢查询的阈值可以通过配置指定:

  • slowlog-log-slower-than: 慢查询阈值,单位是微秒。默认是 10000,建议 1000,通过config set slowlog-log-slower-than 1000设置

  慢查询会被放入慢查询日志中, 日志的长度有上限,可以通过配置指定:

  • slowlog-max-len: 慢查询日志 (本质是一个队列)的长度。默认是128, 建议1000,tong gconfig set slowlog-max-len 1000设置

安全配置

  Redis 会绑定在0.0.0.0:6379, 这样将会将 Redis 服务暴露到公网上, 而 Redis 如果没有做身份认证, 会出现严重的安全漏洞.

  漏洞出现的核心的原因有以下几点:

  • Redis 未设置密码
  • Linux 使用了 root 账号权限启动 Redis
  • 利用了 Redis 的config set命令动态修改 Redis 配置

  为了避免这样的漏洞,这里给出一些建议:

  • ① Redis一定定要设置密码
  • ② 禁止线上使用下面命令: keys、flushall、 flushdb、 config set等命令。可以利用rename-command禁用
  • ③ bind:限制网卡,禁止外网网卡访问
  • ④ 开启防火墙
  • ⑤ 不要使用 root 账户启动 Redis
  • ⑥ 尽量不是有默认的端口

内存配置

  当 Redis 内存不足时,可能导致 Key 频繁被删除、响应时间变长、QPS 不稳定等问题。当内存使用率达到 90% 以上时就需要我们警惕,并快速定位到内存占用的原因。

内存类型 说明
数据内存 Redis 最主要的部分,存储键值信息。主要问题是 BigKey 问题、内存碎片问题
进程内存 Redis 主进程本身运行肯定需要占用内存,如代码、常量池等等;这部分内存大约几兆,在大多数生产环境中与 Redis 数据占用的内存相比可以忽略。
缓冲区内存 一般包括客户端缓冲区、AOF 缓冲区、复制缓冲区等。客户端缓冲区又包括输入缓冲区和输出缓冲区两种。这部分内存占用波动较大,不当使用 BigKey,可能导致内存溢出

Redis提供了一些命令,可以查看到Redis目前的内存分配状态:

  • info memory
  • memory <key_name>

内存缓冲区配置

  内存缓冲区常见的有三种:

  • 复制缓冲区:主从复制的repl_backlog_buf,如果太小可能导致频繁的全量复制, 影响性能。通过repl-backlog-size来设置,默认1mb
  • AOF 缓冲区: AOF 刷盘之前的缓存区域, AOF 执行 rewrite 的缓冲区。 无法设置容量上限
  • 客户端缓冲区:分为输入缓冲区和输出缓冲区, 输入缓冲区最大 1G 且不能设置。 输出缓冲区可以设置
0%