Redis两种方式实现限流

redis的两种限流方式

转自:https://blog.csdn.net/weixin_33869377/article/details/86258460

案例-实现访问频率限制: 实现访问者 $ip 在一定的时间 $time 内只能访问 $limit 次.
  • 非脚本实现
private boolean accessLimit(String ip, int limit, int time, Jedis jedis) {    boolean result = true;    String key = "rate.limit:" + ip;    if (jedis.exists(key)) {        long afterValue = jedis.incr(key);        if (afterValue > limit) {            result = false;        }    } else {        Transaction transaction = jedis.multi();        transaction.incr(key);        transaction.expire(key, time);        transaction.exec();    }    return result;}
  • 以上代码有两点缺陷
    1. 可能会出现竞态条件: 解决方法是用 WATCH 监控 rate.limit:$IP 的变动, 但较为麻烦;
    2. 以上代码在不使用 pipeline 的情况下最多需要向Redis请求5条指令, 传输过多.

  • Lua脚本实现
    Redis 允许将 Lua 脚本传到 Redis 服务器中执行, 脚本内可以调用大部分 Redis 命令, 且 Redis 保证脚本的原子性:
    • 首先需要准备Lua代码: script.lua
---- Created by IntelliJ IDEA.-- User: jifang-- Date: 16/8/24-- Time: 下午6:11-- local key = "rate.limit:" .. KEYS[1]local limit = tonumber(ARGV[1])local expire_time = ARGV[2] local is_exists = redis.call("EXISTS", key)if is_exists == 1 then    if redis.call("INCR", key) > limit then        return 0    else        return 1    endelse    redis.call("SET", key, 1)    redis.call("EXPIRE", key, expire_time)    return 1end
  • Java
private boolean accessLimit(String ip, int limit, int timeout, Jedis connection) throws IOException {    List<String> keys = Collections.singletonList(ip);    List<String> argv = Arrays.asList(String.valueOf(limit), String.valueOf(timeout));    return 1 == (long) connection.eval(loadScriptString("script.lua"), keys, argv);}// 加载Lua代码private String loadScriptString(String fileName) throws IOException {    Reader reader = new InputStreamReader(Client.class.getClassLoader().getResourceAsStream(fileName));    return CharStreams.toString(reader);}

  • Lua 嵌入 Redis 优势:
    1. 减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;
    2. 原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;
    3. 复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.

猜你喜欢

转载自blog.csdn.net/hbn1326317071/article/details/99699442