Redis中如何实现限流?

Redis 可以通过以下几种方式实现限流:

  1. 使用 Redis 的命令时间戳实现简单限流:
  • 在一定时间窗口内,同一个键只允许执行指定次数的命令。
  • 如果超过限定次数,则返回错误信息拒绝请求。
    例如:
// 前5秒钟内同一个用户最多执行10次命令 
if (jedis.commandTypeName("some_key").getTimestamp() > System.currentTimeMillis() - 5000 && 
    jedis.commandTypeName("some_key").getCount() > 10) {
    return jedis.commandTypeName("some_key").error("User exceed request limit"); 
}
  1. 使用 HyperLogLog 统计用户操作次数,并设置最大操作阈值实现限流:
    例如:
// 用户操作计数器,前5秒最多20次
Jedis jedis = new Jedis("localhost");
String hllKey = "user:hll:counter";

if (jedis.pfCount(hllKey) > 20 && jedis.pfAdd(hllKey, "user_id") > 1) {
   return "User exceed request limit";  
}
jedis.pexpire(hllKey, 5000); // 5秒过期
  1. 使用 Redis 的发布订阅模式限制用户操作频率:
  • 用户操作时向频道名为用户ID的频道发布消息。
  • 一个监听者监听所有用户频道,统计短时间内每个频道接收到的消息条数。
  • 如果某频道消息超过限定数量,则拒绝用户请求。
    例如:
// 监听者
jedis.subscribe(new JedisPubSub() {
  public void onMessage(String channel, String message) {
    int count = counts.getOrDefault(channel, 0) + 1;
    counts.put(channel, count);
    if (count > 20) {  // 20秒内超过20条信息,拒绝请求
        jedis.publish(channel, "reject"); 
    } 
  }
}, "user:*"); // 监听所有用户频道

// 用户操作发布消息 
jedis.publish("user:1", "command");