• redis lua 限流的理解误区


    redis lua 限流有很多种方式, 本文分析一种最简单的最常见的方式。

        --获取KEY
        local key1 = KEYS[1]
        
        --获取参数
        local avg1 = ARGV[1]
        local avg2 = ARGV[2]
        
        --打印日志到reids
        --注意,这里的打印日志级别,需要和redis.conf配置文件中的日志设置级别一致才行
        redis.log(redis.LOG_WARNING,"key1=" ..key1)
        redis.log(redis.LOG_WARNING,"avg=" ..avg1, avg2)
        
        --将参数String转为数字类型
        --限流时间窗
        local expire = tonumber(ARGV[1])
        redis.log(redis.LOG_WARNING,"时间窗=" ..expire)
        
        --限流阈值
        local limit = tonumber(ARGV[2])
        redis.log(redis.LOG_WARNING,"限流频次=" ..limit)
        
        --当前并发数
        local current = tonumber(redis.call('get', key1) or "0")
        redis.log(redis.LOG_WARNING,"当前并发=" ..current)
        
        if current + 1 > limit then
         -- redis.call("INCRBY", key,"1") -- 如果不需要统计真是访问量可以不加这行   
    return 0 else   redis.call("INCRBY", key1, "1")   redis.call("expire", key1, expire)   return 1 end

    这个脚本的作用是什么呢?

    我的理解是一个累计计数器, 只要累计计数没有达到 limit,那么就允许流量,同时,如果某个操作之后空闲超过 窗口(即过期时间),那么重新计数。

    redis.call("expire", key1, expire) 是关键一句,这个命令的作用是刷新过期时间, 相当于是延长key 的生命周期;空闲超过指定值,则重新计数。。

    如果 窗口内 累计计数达到 limit,那么能否继续请求呢? 不会,它直接返回0, 需要等待窗口结束(即过期之后)才可以继续接受流量请求。

    此种方式限流, 有点像是滑动窗口, 不允许突发流量。 虽然简单,但如果长时间的流量累计达到了limit ,也要被限流,感觉就不太好。比如 窗口是10s,limit 是100,我每9s发送一个请求,那么会被限流吗? 会的,测试发现只有达到了 limit 就会。 计算一下就是 9 * 100 s = 15min 。

    就是说,虽然非常低的流量速率,但是仍然会被限流,所以感觉不是很实用,某些时候还是需要 令牌桶。

    为什么它会这么流行,是我理解错了吗?


    版权声明
    本文原创发表于 博客园,作者为 阿K .     本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    欢迎关注本人微信公众号:觉醒的码农,或者扫码进群:

  • 相关阅读:
    LeetCode【21】 Merge Two Sorted Lists
    LeetCode【2】Add two numbers
    LeetCode【125】Valid Palindrome
    LeetCode【9】Palindrome Number
    LeetCode【20】Valid Parentheses
    LeetCode【1】Two Sum
    LeetCode【8】string to integer(atoi)
    LeetCode【168】Excel Sheet Column Title
    lambda表达式
    UML类图
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/14494156.html
Copyright © 2020-2023  润新知