redis滑动窗口如何清理冷数据?

目前准备用redis实现分布式限流策略, 抛开那些redis插件,我觉得zset实现理论上可行, 具体逻辑可以是这样:

  1. 抽象限流逻辑: 针对某个action,需要在一段时间(即为窗口),只能容许N个操作
  2. redis伪代码
func increment(key, windowInSecond) {
    Long 当时时间 = System.currentTimeMillis();
    long maxScoreMs = 当时时间 - windowInSecond * 1000;
    // 只留下滑动窗口的数据
    redis.zremrangeByScore(key, 0, maxScoreMs);
    // incre这一次的操作
    redis.zadd(key, 当时时间, 当前时间 + 随机值);
}

func getCount(key) {
    return redis.acard(key);
}

问题:
假设某个行为有大量的不同样本或者不同实例在调用, 也就是key不一样, 假设有百万以上,但是每个key的行为发生次数有限,例如就一次, 这个时候就会出现很大冷数据

处理该问题的方案:

  1. 窗口设置expire, 但是这个时候窗口策略就不是100%准确, 例如: 窗口即将过期发生操作行为N-1次, 窗口过期立刻新建又发生N-1次,这时候策略没有限流?
  2. 限流冷key被动删除, 但是我觉得这个策略太low了, 我为了限流还得写被动删除脚本.

想问下大家, 有没有更优的方案, 或者针对分布式限流, 有没有更好的策略

阅读 3.3k
1 个回答

设置一个过期时间就行了。数据超过这个时间之后,Redis就会自动删除这些数据。或者弄一个定时任务,定一个时间清理窗口里的冷数据
可以看看 redis设计与实现这本书
思否往期相关回答:redis 遇到冷数据过多怎么办,怎么处理?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进