云数据库Redis增强版(Tair)性能增强系列的TairHash数据结构支持高效的动态淘汰策略,可以快速释放内存空间,代价则是会提高TairHash数据的内存消耗。本章节为您介绍TairHash的内存消耗情况和两种淘汰策略,帮助您在淘汰效率和内存消耗间寻找平衡点,降低业务成本。

原生Redis hash与TairHash占用内存的对比测试

在不设置过期时间时,原生Redis hash与云数据库Redis增强版(Tair)性能增强系列的TairHash结构占用的内存相差很小,详细对比请参见下方测试。

  • 测试一

    测试环境

    测试对象 测试命令 测试条件
    TairHash EXHSET tairhashkey field value
    • field大小:1 KB。
    • value大小:1 KB。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    原生Redis hash HSET hashkey field value

    测试结果

    field数量 TairHash占用内存 原生Redis hash占用内存
    10000 29.79 MB 29.79 MB
    100000 297.02 MB 297.02 MB
    1000000 2.9 GB 2.9 GB
  • 测试二

    测试环境

    测试对象 测试命令 测试条件
    TairHash EXHSET tairhashkey field value
    • field大小:64 Byte。
    • value大小:10 KB。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    原生Redis hash HSET hashkey field value

    测试结果

    field数量 TairHash占用内存 原生Redis hash占用内存
    10000 104.17 MB 103.79 MB
    100000 1.02 GB 1.02 GB
    1000000 10.19 GB 10.19 GB
  • 测试三

    测试环境

    测试对象 测试命令 测试条件
    TairHash EXHSET tairhashkey field value
    • field大小:64 Byte。
    • value大小:64 Byte。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    原生Redis hash HSET hashkey field value

    测试结果

    field数量 TairHash占用内存 原生Redis hash占用内存
    10000 2.39 MB 2.02 MB
    100000 25.33 MB 19.31 MB
    1000000 253.29 MB 191.1 MB

从以上测试可以看出,在没有淘汰策略影响的情况下,原生Redis hash与TairHash的内存占用量相近甚至相同。但如果为TairHash field加上过期时间,淘汰策略就会对TairHash的内存占用量产生影响。

TairHash淘汰策略解析

与原生Redis类似,Tair性能增强系列的TairHash结构也支持两种淘汰策略:主动淘汰(Active Expiration)和被动淘汰(Passive Expiration)。

  • 主动淘汰
    TairHash的被动淘汰策略与原生Redis有所不同:
    • 原生Redis会运行周期性任务,每次在设置了过期时间的key中随机选择一个,检查其是否过期,如果过期则将其淘汰,如果没有过期则不淘汰,效率比较低下。
    • Tair性能增强系列也会通过周期性任务来检查所有设置了过期时间的TairHash field,如果该field已经过期,则将其删除并释放其占用的内存,但Tair性能增强系列使用最小堆(min-heap)将TairHash field按过期时间全排序,每次选取的一定是过期时间最小的field。这种主动淘汰方式的优点是效率比原生Redis高,缺点是会产生额外的内存消耗,详细说明请参见主动淘汰策略内存消耗分析
  • 被动淘汰
    TairHash的被动淘汰策略与原生Redis相似,客户端访问已过期的TairHash field时,会触发被动淘汰策略,删除该field并释放内存。TairHash被动淘汰流程举例如下:
    1. 一个TairHash field刚刚过期,尚未被主动淘汰,此时客户端使用EXHGET命令来获取该field。
    2. Redis实例判断这个field是否过期。
    3. 由于该field已经过期,Redis实例会直接将其删除,并释放其占有的内存,然后向客户端返回一个空值。
    被动淘汰优点是几乎没有额外的内存消耗,缺点是如果一个field在过期后一直没有被访问,那么其占用的内存将一直得不到释放。

两种淘汰策略的生效规则请参见淘汰策略生效规则。在实际业务中,建议结合使用主动淘汰和被动淘汰两种策略,详细说明请参见最佳实践

淘汰策略生效规则

TairHash淘汰策略生效规则如下:

  • 默认同时开启主动淘汰和被动淘汰。
  • 被动淘汰策略对所有设置了过期时间的TairHash field生效。
  • 主动淘汰策略对每个field单独生效。使用可以为TairHash设置过期时间的命令时,添加NOACTIVE选项即可取消对目标field的主动淘汰。
    说明 TairHash命令列表及详细使用说明请参见TairHash命令

由此可见,如果在设置过期时间时不添加NOACTIVE选项,主动淘汰策略就会生效,产生额外的内存消耗。这些额外内存消耗的详细说明请参见主动淘汰策略内存消耗分析

主动淘汰策略内存消耗分析

为了提高主动淘汰效率,Tair性能增强系列内部使用一个min-heap(最小堆)将field按过期时间进行全排序并建立索引。每当一个TairHash field被设置了过期时间,实例就会创建一个最小堆节点(heap node)并将其加入到min-heap中,heap node中保存着对key和field的索引,以便在heap node过期时找到对应的TairHash和field,从而将其删除并释放内存。由于heap node增加了对key和field的引用,key和field占用的内存在命令执行完时无法被立即释放,因此,相对于单纯使用被动淘汰策略,使用主动淘汰策略时多出了如下内存消耗:

  • 所有heap node本身占用的内存
  • key占用的内存
  • 所有带有过期时间的field本身占用的内存

您可以通过下方的对比测试直观地了解不同淘汰策略下TairHash的内存占用情况。

不同淘汰策略下TairHash占用内存的对比测试

  • 测试一

    测试环境

    测试对象 测试命令 测试条件
    无过期时间的TairHash EXHSET tairhashkey field value
    • field大小:1 KB。
    • value大小:1 KB。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    有过期时间的TairHash EXHSET tairhashkey field value EX 1000

    测试结果

    field数量 无过期时间的TairHash占用内存 有过期时间的TairHash占用内存
    10000 29.79 MB 46.03 MB
    100000 297.02 MB 460.36 MB
    1000000 2.9 GB 4.6 GB
  • 测试二

    测试环境

    测试对象 测试命令 测试条件
    无过期时间的TairHash EXHSET tairhashkey field value
    • field大小:64 Byte。
    • value大小:64 Byte。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    有过期时间的TairHash EXHSET tairhashkey field value EX 1000

    测试结果

    field数量 TairHash占用内存 原生Redis hash占用内存
    10000 2.39 MB 4.38 MB
    100000 25.33 MB 45.16 MB
    1000000 253.29 MB 451.66 MB
  • 测试三

    测试环境

    测试对象 测试命令 测试条件
    无过期时间的TairHash EXHSET tairhashkey field value
    • field大小:64 Byte。
    • value大小:64 Byte。
    • 关闭AOF与RDB备份。
    • 实例为单节点,无副本。
    • 设置过期时间时通过NOACTIVE选项关闭主动淘汰。
    有过期时间的TairHash EXHSET tairhashkey field value EX 1000 NOACTIVE

    测试结果

    field数量 TairHash占用内存 原生Redis hash占用内存
    10000 2.39 MB 2.39 MB
    100000 25.33 MB 25.33 MB
    1000000 253.29 MB 253.29 MB

最佳实践

TairHash为以下命令提供了NOACTIVE选项:

  • EXHSET
  • EXHEXPIRE
  • EXHEXPIREAT
  • EXHPEXPIRE
  • EXHPEXPIREAT
  • EXHINCRBY
  • EXHINCRBYFLOAT

淘汰策略生效规则可知,在使用上述命令为TairHash field设置过期时间时,不设置NOACTIVE选项就会激活主动淘汰。如果设置了NOACTIVE,则主动淘汰策略不会应用于目标field,也不会产生额外的内存消耗,但缺陷也很明显:field过期后,只要没有被访问,占用的内存空间就不会被释放。

注意 使用EXHGETALLEXHKEYSEXHVALSEXHSCAN命令访问TairHash不触发被动淘汰,不会删除过期field并释放内存。为了尽可能快地响应客户端,降低产生慢查询的风险,这些命令只会把过期的field从返回结果中过滤掉。
建议您根据业务特点决定是否使用主动淘汰策略,或者对哪些数据使用主动淘汰策略。例如:
  • 在数据过期时间短、数据量增长快的场景,推荐尽量采用主动淘汰策略,在数据过期后快速将其淘汰,释放内存给新的数据。
  • 在数据过期时间长、数据量增长较慢的场景,可以少采用或者不采用主动淘汰策略,这样反而能降低总体内存消耗。
  • 在冷热数据分界清晰的场景,您还可以对访问频率较低的数据采用主动淘汰策略,提高内存释放效率,而在写入热点数据时通过NOACTIVE选项取消主动淘汰,兼顾淘汰效率与内存消耗。