lua advantages
Reduce network overhead: code without Lua needs to send multiple requests to Redis, while script only needs one time to reduce network transmission;
Atomic operation: Redis executes the entire script as an atom without worrying about concurrency or transaction;
Reuse: the script will be permanently saved in Redis, and other clients can continue to use it
Counter mode:
Use lua script to finish processing at one time to achieve atomicity, judge whether it reaches the limit value through INCR auto increment count, return the current limit when it reaches the limit value, and the expiration time of adding key should be too long
$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 request code:
Redis::eval($lua, 3, sprintf(RedisKey::API_LIMIT, $key, $callService['service']), 60, $cache_key);
Token bucket mode
Each request takes a token in the bucket. If there is a token, it will pass. Otherwise, it will return, and put the token into the bucket slowly according to the algorithm
$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 parameter);