如何处理数据倾斜

云数据库 Tair(兼容 Redis)集群架构实例中,若个别数据分片节点(Data Node)的内存使用率、CPU使用率或带宽使用率等性能指标远远高于其他数据分片,该集群可能已产生数据倾斜。数据倾斜严重时,会导致实例在整体内存使用率不高的情况下,发生内存逐出(Key eviction)、内存溢出OOM(Out Of Memory)、实例响应时间上升等异常情况。

快速处理

本章节介绍如何确认是否存在数据倾斜,以及查找、处理大Key的方法。

  1. 访问CloudDBA > 实时性能,查看各数据分片节点的内存使用率是否均衡。

    本示例中,db-0数据分片节点的内存使用率显著高于其他数据分片节点,该实例存在数据倾斜。image

    说明

    您还可以使用实例诊断功能,一键排查当前实例是否存在倾斜的情况。

  2. 查看每个数据分片节点的Key总数。

    在本示例中,可以看到db-0、db-1和db-2数据分片节点的Key总数分别是2.59、2.60和2.59 Million(百万)个,各数据分片节点中Key数量是相对均衡的,此时大概率可以确定db-0数据分片节点中存在大Key

    说明

    若各数据分片节点的Key数量不均衡,则表示业务中可能存在Key名称设计不规范,例如使用了Hash Tags等,客户端在通过CRC算法时,将Key都写至同一数据分片节点中。此时您需要从业务侧进行改造,避免在Key名称中使用{}

  3. 使用离线全量Key分析功能,快速找出大Key。

    该功能将分析实例的备份文件,不会对在线业务产生影响。分析完成后,您可以查看Top 500 BigKey,在本示例中,名为mylist的Key为大Key。

    image

  4. (可选)您也可以连接到具体的数据分片节点中,进行查询与分析。

    • 集群架构代理模式:可以使用阿里云自研的ISCAN命令,在指定的数据分片节点上执行SCAN命令,更多信息请参见阿里云自研的Proxy命令

    • 集群架构直连模式:可以通过DescribeDBNodeDirectVipInfo API接口获取各数据分片节点的VIP,再通过客户端连接待分析的数据分片节点进行分析。

  5. 解决方案。

    • 临时:升级实例规格。

    • 长期(推荐):进行业务改造,合理地拆分大Key。

关于导致数据倾斜的详细原因和处理方法请见下文,本文也适用于排查标准架构内存使用率、CPU使用率、带宽使用率和延迟等性能指标高的问题。

为什么会产生数据倾斜

云数据库 Tair(兼容 Redis)集群架构实例作为一个分布式系统,整个数据库空间会被分为16384个槽(Slot),每个数据分片节点将存储与处理指定Slot的数据(Key),例如3分片集群实例,3个分片分别负责的Slot为:[0,5460]、[5461,10922]、[10923,16383]。当用户写入或更新数据时,客户端会通过CRC算法计算出Key所属的Slot,具体公式为Slot=CRC16(key)%16384,并将数据写入Slot所属的数据分片节点。通常情况下,各数据分片节点的Key数量是均匀分布的,同时内存使用率、CPU使用率等性能指标也是相近的。

但在使用数据库的过程中,可能会由于前期规划不足、不规范的数据写入及突发的访问量,造成数据量倾斜或数据访问倾斜,最终引起数据倾斜。

说明
  • 数据倾斜通常是指大多数据分片节点的性能指标较低,而个别节点的性能指标较高的情况,高或低没有明确的标准。您可以在性能监控数据节点页面中查看各数据分片节点的对应指标,通常情况下,若某数据分片节点(最高)的性能指标高出其他数据分片节点(最低)20%及以上时,可认为已产生数据倾斜,差值越大,数据倾斜程度越严重。

  • 当单数据分片节点的内存使用率达100%时,该数据分片节点会触发数据逐出(默认策略为volatile-lru)。

下图介绍两个典型的数据倾斜场景,如下图所示,虽然Key均匀地分布在集群中,每个数据分片节点2个Key,但仍产生了数据倾斜:

image
  • Shard 1节点中key1的QPS明显高于其他Key,属于典型的数据访问倾斜,会导致该Key所在的数据分片节点CPU使用率、带宽使用率升高,从而影响该分片上所有Key的处理。

  • Shard 2节点中key5的QPS虽然不高,但该Key的大小为1 MB,属于典型的数据量倾斜,会导致该Key所在的数据分片节点的内存使用率、带宽使用率升高,从而影响该分片上所有Key的处理。

临时方案

因此,若实例已产生数据倾斜,您可以通过如下临时方案进行过渡。

倾斜场景

可能原因

临时方案

内存倾斜

大Key、Hash Tags。

升级实例规格,具体操作请参见变更实例配置

重要
  • 变配时实例会进行数据倾斜预检查,若您选择的实例规格无法解决内存倾斜问题,实例会进行拦截与报错,请您调大实例规格后重试。

  • 在成功升级实例规格后,会改善内存倾斜问题,但可能也引起带宽倾斜或CPU倾斜。

带宽倾斜

大Key、热Key、高消耗命令。

提升实例中指定1个或多个分片的带宽,具体操作请参见手动增加实例带宽

说明

单个实例分片可增加带宽的上限为192MB/s,若业务流量仍大于该值,则只能在业务层进行改造。

CPU使用率倾斜

大Key、热Key、高消耗命令。

  • 如果热点Key分布在不同Slot,可以尝试在业务低峰期增加数据分片节点,使热点Key分散。

  • 优化高消耗命令,例如减少每次SCAN命令获取Key的数量。

说明

请在业务低峰期扩容,因为扩容期间数据迁移操作会消耗CPU。

同时,您也可以在短时间内可降低大Key、热Key的请求量,暂缓数据倾斜问题,但大Key、热Key问题只能通过业务上的改造才能解决。建议您及时对实例进行数据倾斜的原因排查,并根据对应处理方法在业务层进行改造,对实例进行优化,更多信息请参见多种数据倾斜原因的处理方法

多种数据倾斜原因的处理方法

请提前规划业务增长率,合理地拆分大Key,并保持规范的数据写入,才能解决数据倾斜的根源问题。

产生倾斜原因

说明

处理方法

大Key

大Key通常以Key的大小和Key中成员的数量来综合判定。

常见于在KKV(Key-key-value)类型的数据结构中,例如Hash、List、Set、Zset等,存放过多或过大的field,从而导致单个Key过大,产生实例数据倾斜。

关于如何在不影响业务的情况下,优雅地删除大Key或热Key,请参见优化大Key与热Key

  • 避免使用大Key。

  • 对大Key进行拆分,例如将含有数万成员的一个HASH Key拆分为多个HASH Key,并确保每个Key的成员数量在合理范围。

热Key

热Key指某个Key或者少部分Key的操作QPS明显高于其他Key。常见于压测时选了单一Key或秒杀场景下热点商品ID Key。更多关于热Key信息,请参考发现并处理大Key和热Key

  • 请避免使用热Key。

  • 使用QueryCache特性,缓存热点数据,更多信息请参见优化大Key与热Key

高消耗命令

不同的命令具有不同的复杂度,高复杂度的命令会消耗大量性能资源,例如HGETALL命令的复杂度为O(n),该命令会随着您存储的Field越多,消耗越大。同时,简单的SETGET命令也会在Value过大时,消耗大量数据分片节点的性能资源。

  • 可通过查询慢日志功能查询数据分片节点的慢日志。

  • 可通过时延洞察查看消耗大量性能资源的命令。

  • 业务侧需减少或禁止使用高消耗命令,如需禁用命令,可以在参数设置中配置#no_loose_disabled-commands参数。

Hash Tags

若Key名称中包含{},例如{item}id1,则Tair仅会对{}中的内容进行Slot计算并选择数据分片节点。若存在{item}id1{item}id2{item}id3等大量Key,由于{}中的内容相同,上述Key均会被分配至同一数据分片节点,导致该数据分片节点的内存资源、性能消耗大幅升高。

  • 避免在Key名称中使用{}

    说明

    如需在Key名称中使用{},需保证{}中的内容尽可能不同,从而使Key尽量均匀地分布在集群的不同数据分片节点上。

常见问题

  • Q:集群实例中有大Key,可以升级大Key所在的数据分片节点的实例规格吗?

    A:不可以,云数据库 Tair(兼容 Redis)实例不支持单独升级某个分片节点的实例规格,仅支持同时升级所有分片节点的实例规格。

  • Q:集群实例中有大Key,新增分片节点并重新分布Key可以解决该问题吗?

    A:不会解决,新的分片节点会帮原有分片节点分担部分内存压力。但云数据库 Tair(兼容 Redis)的数据分布粒度为Key级,大Key是无法被自动拆分的。由于大Key没被解决掉,在重新分布Key后,仍会一个分片节点的内存是高于其他分片节点,此时仍存在数据倾斜。推荐的方法是拆分大Key,让大Key变成多个小Key。