您的位置:首页 > 编程学习 > > 正文

phpredis怎么设置队列(php使用lua+redis实现限流,计数器模式,令牌桶模式)

更多 时间:2022-03-30 14:04:58 类别:编程学习 浏览量:1947

phpredis怎么设置队列

php使用lua+redis实现限流,计数器模式,令牌桶模式

lua 优点

减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;

原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;

复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.

计数器模式:

利用lua脚本一次性完成处理达到原子性,通过INCR自增计数,判断是否达到限定值,达到限定值则返回限流,添加key过期时间应该范围过度

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • $lua = '
  •         local i = redis.call("INCR", KEYS[1])
  •         if i > 10 then
  •           return "wait"
  •         else
  •           if i == 1
  •           then
  •             redis.call("expire", KEYS[1], KEYS[2])
  •           end
  •           return redis.call("get", KEYS[3])
  •         end
  •       ';
  • laravel 请求代码:

  • ?
  • 1
  • Redis::eval($lua, 3, sprintf(RedisKey::API_LIMIT, $key, $callService['service']), 60, $cache_key);
  • 令牌桶模式

    每次请求在桶内拿取一个令牌,有令牌则通过,否则返回,并且按照算法一定的慢慢把令牌放入桶内

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • $lua = '
  •         local data = redis.call("get", KEYS[2])
  •         if data then
  •         
  •           local dataJson = cjson.decode(data)
  •           local newNum = math.min(KEYS[3], math.floor(((dataJson["limitVal"] - 1) + (KEYS[3]/KEYS[5]) * (KEYS[4] - dataJson["limitTime"]))))
  •           
  •           if newNum > 0 then
  •           
  •             local paramsJson = cjson.encode({limitVal=newNum,limitTime=KEYS[4]})
  •             redis.call("set", KEYS[2], paramsJson)
  •             return redis.call("get", KEYS[1])
  •           
  •           end
  •            return "wait"
  •         end
  •         
  •         local paramsJson = cjson.encode({limitVal=KEYS[3],limitTime=KEYS[4]})
  •         redis.call("set", KEYS[2], paramsJson)
  •         return redis.call("get", KEYS[1])
  •       ';
  •       
  •       // 1. lua脚本, 2 KEYS数量, 3 查找数据key, 4 限制key, 5 桶内数量, 6 时间戳, 7 过期时间
  •       Redis::eval(1,2,3,4,5,6,7参数);
  • 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    原文链接:https://segmentfault.com/a/1190000018761106