MST

星途 面试题库

面试题:Redis KEYS命令在复杂场景下的优化使用

假设Redis数据库中有海量的键,这些键的命名规则较为复杂,一部分键以'app:module1:'开头,另一部分以'app:module2:'开头,并且在模块名后跟着不同业务类型(如'user'、'product'等),之后再跟着具体的ID。例如'app:module1:user:123'、'app:module2:product:456'。现在要求设计一种方案,使用KEYS命令(或结合其他命令)快速统计出'app:module1'下不同业务类型的键的数量,同时要尽量减少对Redis性能的影响,详细阐述你的思路和实现步骤。
24.9万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试
  1. 思路
    • KEYS命令在生产环境中应谨慎使用,因为它是全量扫描,对性能影响大。但本题要求尽量减少影响,所以可以采用分批次扫描的方式。
    • 先使用SCAN命令迭代获取所有以app:module1:开头的键,然后对获取到的键进行分析统计不同业务类型的键的数量。
  2. 实现步骤
    • 使用SCAN命令获取键
      • 初始化游标为0,即cursor = 0
      • 使用SCAN命令,每次迭代获取一定数量(如count = 100)的键,命令格式为SCAN cursor MATCH app:module1:* COUNT count。这里MATCH选项用于筛选出以app:module1:开头的键,COUNT选项指定每次迭代返回的键的数量。
      • 执行SCAN命令后,返回结果是一个数组,第一个元素是新的游标值,若为0表示迭代结束;第二个元素是本次迭代获取到的键的数组。
    • 统计不同业务类型的键的数量
      • 初始化一个字典(在编程语言中,如Python中的dict)用于存储不同业务类型的键的数量,例如count_dict = {}
      • 对每次迭代获取到的键数组进行遍历,以:为分隔符分割键,获取业务类型(即分割后的第三个元素)。
      • 如果业务类型已经在count_dict中,则将其对应的值加1;否则,在count_dict中添加该业务类型,并将其值设为1。
    • 循环执行SCAN直到结束
      • 将每次SCAN返回的新游标值赋给cursor,继续执行SCAN命令,直到cursor0
    • 最终结果
      • 最终count_dict中存储的就是app:module1下不同业务类型的键的数量。

例如在Python中实现如下(假设使用redis - py库):

import redis

r = redis.Redis(host='localhost', port = 6379, db = 0)
cursor = '0'
count_dict = {}
while cursor!= '0':
    cursor, keys = r.scan(cursor = cursor, match = 'app:module1:*', count = 100)
    for key in keys:
        parts = key.decode('utf - 8').split(':')
        if len(parts) > 2:
            business_type = parts[2]
            if business_type in count_dict:
                count_dict[business_type] += 1
            else:
                count_dict[business_type] = 1
print(count_dict)