• 技术文章 >数据库 >Redis

    redis可以采用什么方式实现限流

    我叫mt我叫mt2021-01-20 09:16:57转载635

    目的:

    (学习视频分享:redis视频教程

    非脚本实现

    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; }

    以上代码有两点缺陷

    可能会出现竞态条件: 解决方法是用 WATCH 监控 rate.limit:$IP 的变动, 但较为麻烦;以上代码在不使用 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 end else redis.call("SET", key, 1) redis.call("EXPIRE", key, expire_time) return 1 end

    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 优势:

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

    相关推荐:redis数据库教程

    以上就是redis可以采用什么方式实现限流的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:csdn,如有侵犯,请联系admin@php.cn删除
    专题推荐:redis 限流
    上一篇:windows下打开redis后闪退怎么办 下一篇:详解Jedis对redis的操作

    相关文章推荐

    • Java架构师之路--限流技术和各类编程语言• nginx怎么限流• 笔记本上网卡有无限流量的吗• nginx实现限流的方式有哪几种

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网