性能调优最佳实践

最终更新于 2024 年 4 月 18 日

问题

在本文中,你可以找到操作 Redis Enterprise 数据库的最佳实践。其中一些建议也适用于 Redis Community 部署,尤其是在处理适当的数据类型和命令、密切关注命令复杂性时。

Redis 命令

  • 查看 EVALSHAHGETALLHMGETMGET 和所有类型的 SCAN 命令的慢日志。降低慢日志阈值,以捕获更多慢命令。你可以使用 CONFIG SET slowlog-log-slower-than <THRESHOLD_MICROSECONDS> 配置阈值
  • 避免使用 KEYS 命令,该命令会扫描整个键空间。
  • 在计算真正的 ops/s 时考虑 MGET 命令。例如,在 32k ops/s 时执行 10 个键的 MGET 等于 320k ops/s。

热键和大键

  • 使用 redis-cli --bigkeysredis-cli --hotkeys 验证键的大小(仅适用于非 CRDB 数据库)。当对大键(例如扫描)进行操作导致 CPU 使用率较高时,分片并不会有帮助。可以将大键拆分成小键以减轻负载
  • 建议还限制范围的大小,任何命令(ZREVRANGEZRANGEZREVRANGEBYSCORE 等)都可以,只要不执行全范围(0-1)即可。范围越小越好。然后在大型集合上,我们建议使用 ZRANGE(或其他范围扫描命令)搭配定义的范围,而不是完全扫描
  • 如果可能,避免无界 LRANGE 调用,它们可能产生高延迟。使用范围。 如果它是时间序列,则可以在不同的数据结构中更有效地对其进行处理。

删除

使用异步 UNLINK 而不是同步 DEL 删除巨大键。

为了在 Redis 中执行大量键删除而不影响性能,请使用带批量操作的 redis-cli 或 Redis Insight。使用 redis-cli,您可以指示模式并确保

  • 使用 -i 选项,以免阻塞分片的执行
  • 使用 UNLINK,以便在后台执行任务
  -i <interval>      
    When -r is used, waits <interval> seconds per command.                     
    It is possible to specify sub-second times like -i 0.1.

因此使用该命令的一个示例将是

redis-cli -p <PORT> --scan --pattern city:* -i 0.01 | xargs redis-cli -p <PORT> unlink

另外,可以将 xargs-L 选项(最大行数)一起使用,以减少阻塞其他命令服务的可能性。

man xargs

[...]

-L number   Call utility for every number non-empty lines read.

Redis Insight 有一个“批量操作”标签,它可以选择删除键。

  • 在“查找键”格式化字段中,可以提供模式
  • 单击“试运行”按钮
  • 预览窗格返回将 UNLINK 的键列表
  • 单击“执行”按钮执行键删除

持久化和备份

当执行备份或启用持久化(AOF/快照)时,非复制数据库可能会导致延迟。复制数据库解决了副作用,备份收集在复制分片上。相同的行为适用于持久性。

LUA 脚本

验证 LUA 脚本不会因长时间执行而使状态机处于忙碌状态。检查指标“其他命令”,它表示除读取/写入命令(例如非读取/写入命令)之外的其他任何内容。

可扩展性和分片放置

  • 规模扩大。重新分片数据库,以便利用多个内核。如果分片在同一节点中,请保留single 代理策略。
  • 横向扩展。如果 CPU 被占用,请在节点间重新分布分片(如果该数据库未被集群化,请确保操作对于集群是安全的)。
  • 使用相应的 REST API 端点优化分片放置,并评估给定数据库的建议。
  • DMC 代理扩展。如果数据库在多个节点上有分片,请考虑也更改代理策略(all-master-shards),以便 DMC 代理也能扩展。
  • 为 DMC 代理(max_threads)配置和基准不同数量的线程,以确保代理不会出现瓶颈。
  • 检查分片是否已平衡:不平衡可能是由于节点具有不同的特性造成的。使用哈希策略或巨大键也会导致不平衡。

资源

  • 检查从属分片日志中的 AOF 错误:这意味着磁盘速度较慢。管理界面还可以在节点摘要页面报告 "由于达到磁盘 I/O 限制,无法写入磁盘"。警报与磁盘 I/O 限制有关,而不是与存储限制有关。磁盘可能未满,但无法保持速度。例如,如果节点中的所有分片均已启用通过 AOF 进行持久性,则可能会发生这种情况。它与底层硬件有关。
  • 使用 logtop 来捕获任何繁重命令与慢速日志分析一起产生的峰值
  • 确保已禁用交换。Linux 系统可能会交换内存,即使框中的内存不低(特别是具有较高的交换性值时)
  • 内存不足也可能导致代价高昂的驱逐。大量的键驱逐可能会导致延迟高峰,因为数据库必须释放内存。如果集群内存不足并且驱逐策略配置为 volatile-lru,或者仅仅是因为大量键已设置为 EXPIRE,则可能会发生这种情况
  • Redis Enterprise Active-Active 数据库现在支持 MEMORY USAGE 命令,版本从 6.2.18 开始,此命令可简化故障排除并让应用程序检测异常行为和危险趋势。

网络延迟

  • 检查主分片和端点是否位于不同的节点,这还可能增加延迟(所有主分片都靠近代理的情况最佳)
  • 客户端和数据库是否在同一 VPC 或具有对等连接的不同 VPC 中?两者在同一 VPC 中运行可以帮助将每秒数据包数乘以很多倍。

连接池

始终建议使用连接池。否则,每个请求将打开一个新连接。这会暴露出许多潜在的暂时性问题,这些问题可能会阻止打开连接。此外,打开和关闭连接还会产生额外的开销。

几个连接将通过使用连接池处理所有请求,并且不会在每个请求后关闭。这消除了上述问题,并将确保更好的性能,因为无需浪费时间打开和关闭连接。

除非客户端将其关闭或未回复 TCP 保持活动消息,否则 Redis Enterprise 会永久保持连接。对于连续 5 分钟未回答心跳的空闲连接,会关闭:Redis Enterprise 假设客户端关闭了其连接。可以使用 CLIENT LIST 命令验证活动连接的数量。

如果使用池,则可能需要增加池中的最小连接数,以便新线程创建不会延误客户端上的操作。如果不使用池,请评估使用它。

支持连接池的客户端示例

并非所有客户端都提供连接池功能:StackExchange就是一个示例,多路复用一个连接。

管道

使用客户端管道,可以通过将多个命令打包到批处理中节省往返时间。除了将多个命令的累积延迟减少到批处理的延迟外,读取传入消息还需要更少的套接字读取操作,从而节省系统调用和减少总体延迟。了解更多文档

在不同的分片上观察到不均匀的负载

为数据库增加更多分片来利用多核提供的并行性是可行的,但这不总是会有帮助。热分片可能有一些原因。一个原因是该分片上有大的键或键值。要找到它,您可以使用带有 --bigkeys 标志运行 redis-cli 命令。

redis-cli -h <hostname> -p <port> -a <password> --bigkeys

您也可能有热键。为标识这一点,您可以在低流量期运行很短的监测周期(几秒钟)的 MONITOR 命令。请注意,此命令很危险,可能会影响延迟。请先在开发数据库或其他低流量非生产数据库上运行很短的时间并对其进行测试。详细了解MONITOR命令。