Рубрики
Uncategorized

PHP использует Lua + redis для реализации ограничения тока, режима счетчика и модели корзины токенов

Автор оригинала: David Wong.

Преимущества Lua

Уменьшите нагрузку на сеть: код без Lua должен отправлять несколько запросов в Redis, в то время как сценарию требуется только один раз, чтобы уменьшить передачу по сети;

Атомарная операция: redis выполняет весь сценарий как атом, не беспокоясь о параллелизме или транзакции;

Повторное использование: сценарий будет навсегда сохранен в redis, и другие клиенты смогут продолжать его использовать

Счетчик режим:

Используйте сценарий Lua для завершения обработки за один раз, чтобы достичь атомарности, определите, достигает ли он предельного значения с помощью автоматического приращения, верните текущий предел, когда он достигнет предельного значения, и время истечения срока добавления ключа должно быть слишком большим

$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:

Redis::eval($lua, 3, sprintf(RedisKey::API_LIMIT, $key, $callService['service']), 60, $cache_key);

Ведро для токенов режим

Каждый запрос принимает токен в корзине. Если есть жетон, он пройдет. В противном случае он вернется и поместит жетон в

$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 script, 2 number of keys, 3 search for data key, 4 limit key, 5 number in barrels, 6 time stamp, 7 expiration time
      Redis:: Eval (1,2,3,4,5,6,7 parameters);

Выше приведено все содержание этой статьи. Я надеюсь, что это поможет вам в вашем исследовании, и я надеюсь, что вы сможете больше поддерживать developepaer.