MST

星途 面试题库

面试题:Redis多维度限流中如何根据不同维度分配权重

在Redis多维度限流场景下,假设存在用户维度、IP维度和设备维度,现在要为每个维度分配不同权重以实现更精准的限流,请阐述你会如何设计权重分配的逻辑以及利用Redis数据结构和命令来实现?
44.9万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

权重分配逻辑设计

  1. 用户维度:通常用户是核心主体,若应用主要面向个人用户,且希望重点限制单个用户行为,可给予较高权重。比如业务是内容发布,为防止单个用户大量发布垃圾信息,将用户维度权重设为 5。
  2. IP 维度:主要用于防止恶意 IP 攻击。若网络环境复杂,存在大量代理 IP 等情况,可适当给予较低权重,如设为 3,以避免误判正常用户行为。
  3. 设备维度:可作为辅助维度,若应用在多种设备上使用,为防止单个设备异常操作,权重设为 2。

利用 Redis 数据结构和命令实现

  1. 数据结构选择
    • 使用 Redis 的 Hash 结构存储每个维度的限流信息。例如,以 limit:{key} 作为 Hash 的 key,其中 key 可以是用户 ID、IP 地址或设备 ID。Hash 的 field 存储时间窗口相关信息,value 存储对应时间窗口内的访问次数。
    • 例如,limit:user:1 这个 Hash 结构,field 为 10s(表示 10 秒时间窗口),value 为 3(表示 10 秒内访问了 3 次)。
  2. 实现步骤
    • 初始化限流数据:在系统启动或用户首次访问时,为每个维度的 key 在 Redis 中创建对应的 Hash 结构,并初始化时间窗口内的访问次数为 0。
    import redis
    
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    def init_limit(key, time_windows):
        data = {window: 0 for window in time_windows}
        r.hmset(f'limit:{key}', data)
    
    • 每次请求处理:每次请求到达时,根据请求的用户 ID、IP 地址和设备 ID 获取对应的 Hash 结构,更新相应时间窗口内的访问次数。
    def incr_limit(key, time_window):
        current_count = r.hincrby(f'limit:{key}', time_window, 1)
        return current_count
    
    • 限流判断:根据权重分配,计算总访问次数,与设定的限流阈值比较。假设用户权重为 user_weight,IP 权重为 ip_weight,设备权重为 device_weight,限流阈值为 threshold
    def check_limit(user_key, ip_key, device_key, time_window, user_weight, ip_weight, device_weight, threshold):
        user_count = r.hget(f'limit:{user_key}', time_window)
        ip_count = r.hget(f'limit:{ip_key}', time_window)
        device_count = r.hget(f'limit:{device_key}', time_window)
        total_count = (int(user_count) if user_count else 0) * user_weight + \
                      (int(ip_count) if ip_count else 0) * ip_weight + \
                      (int(device_count) if device_count else 0) * device_weight
        return total_count <= threshold
    

通过上述设计和实现,可以在 Redis 中实现多维度带权重的限流。