redis lua限流腳本


lua限流腳本:

local key_local = redis.call('setnx',KEYS[1],0)

if tonumber(key_local) == 0 then
    if tonumber(redis.call('get',KEYS[1]))>=tonumber(ARGV[2]) then
        return false
    else
        redis.call('incr',KEYS[1])
        return true
    end
else
    redis.call('incr',KEYS[1])
    redis.call('pexpire',KEYS[1],ARGV[1])
    return true
end

java調用代碼:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import java.util.Collections;

@Component
public class GlobalLimitComponent {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 針對某個key使用lua腳本進行限流
     * 使用lua優點,可以保證多個命令是一次行傳輸到Redis服務器並且是串行執行的,保證串行執行的命令中不行插入其他命令,防止並發問題
     * 步驟:
     * 1、判斷key是否存在,如果不存在,保存該key,設置值為1,設置多少毫秒(n)最多進行幾次(m)
     * 2、如果值存在,先判斷key是否超時了,如果超時則刪除,並重新執行步驟1,如果key未超時,則判斷是否超過n毫秒最多m次的限制
     *
     * @param key
     */
    public Boolean getGlobalLimitByLua(String key, int mlitimes, int maxCount) {
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/limit.lua")));
        redisScript.setResultType(Boolean.class);

        return redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(mlitimes), String.valueOf(maxCount));
    }
}

優化點:lua腳本不用每次都上傳,可以上傳到redis服務器后獲得hash值,每次調用hash值進行執行;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM