MST

星途 面试题库

面试题:缓存设计:动态场景下Redis大Key的预防与治理

在一个业务不断增长且数据结构动态变化的后端系统中,如何在系统设计层面预防Redis大Key的产生?若大Key还是出现了,怎样在不影响线上业务的前提下,对其进行有效治理?请结合实际案例说明。
29.5万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

预防Redis大Key产生

  1. 数据设计优化
    • 合理拆分数据结构:例如,在电商系统中,原本可能将一个商品的所有信息(包括详细描述、图片URL列表、评论等)存储在一个Hash结构的大Key中。应将其拆分为多个小Key,如商品基本信息一个Key,评论单独一个Key(可以用商品ID作为前缀,如product:1:infoproduct:1:comments)。这样每个Key的数据量相对较小,避免了大Key的产生。
    • 控制集合元素数量:对于Set、List、ZSet等集合类型,在业务允许的情况下,限制每个集合中的元素数量。例如在一个排行榜业务中,若使用ZSet存储用户的积分排行榜,可设置每1000个用户为一组,使用不同的ZSet存储(如rank:1 - 1000rank:1001 - 2000等)。
  2. 业务逻辑优化
    • 避免全量操作:在一些批量处理业务中,如批量更新用户信息,如果直接将所有用户信息整合为一个大Key更新到Redis,易产生大Key。应采用分批处理的方式,每次处理一部分用户信息,逐步更新到Redis。
    • 定期清理无效数据:对于一些时效性较强的数据,如限时活动的缓存数据,在活动结束后及时清理相关Key,防止这些Key不断累积数据变成大Key。

大Key出现后的治理(不影响线上业务)

  1. 数据迁移
    • 异步迁移:使用Redis的SCAN命令(对于Hash类型使用HSCAN,List类型使用LRANGE等)逐步读取大Key中的数据,然后将数据迁移到新的小Key中。例如,在一个社交系统中,有一个大Key存储了某个用户所有的好友关系(List类型),可以使用LRANGE每次读取一部分好友关系,然后插入到新的以用户ID和分页信息命名的小Key中(如user:1:friends:page1user:1:friends:page2等)。在迁移过程中,线上业务仍然可以从原大Key读取数据,待迁移完成后,再切换到新的小Key读写。
    • 影子Redis实例:创建一个影子Redis实例,将大Key的数据逐步迁移到影子实例,并修改线上业务代码,使其在读写时先从影子实例读取,如果影子实例没有再从原实例读取。随着时间推移,大部分业务流量会转移到影子实例,此时可以将原大Key删除,然后将影子实例替换原实例。
  2. 优化存储结构
    • 转换数据结构:例如,如果大Key是一个非常大的Hash结构,且其中部分字段访问频率很低,可以将这些低频字段提取出来,存储到另外一个Key中。比如在一个用户资料存储的Hash大Key中,用户的历史登录IP信息访问频率低,可将其提取到一个新的Key(如user:1:history_ips),原Hash大Key只保留常用信息。这样原大Key的体积会减小,同时不影响高频业务的访问。