這篇文章主要介紹redis能夠采用什么樣的方式來(lái)實(shí)現(xiàn)限流,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)公司-成都網(wǎng)站建設(shè)公司,專(zhuān)注成都網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站營(yíng)銷(xiāo)推廣,域名注冊(cè),網(wǎng)頁(yè)空間,綿陽(yáng)服務(wù)器托管有關(guān)企業(yè)網(wǎng)站制作方案、改版、費(fèi)用等問(wèn)題,請(qǐng)聯(lián)系創(chuàng)新互聯(lián)公司。
目的:
實(shí)現(xiàn)訪(fǎng)問(wèn)頻率限制
實(shí)現(xiàn)訪(fǎng)問(wèn)者 $ip 在一定的時(shí)間 $time 內(nèi)只能訪(fǎng)問(wèn) $limit 次
非腳本實(shí)現(xiàn)
private boolean accessLimit(String ip, int limit, int time, Jedis jedis) { boolean result = true; String key = "rate.limit:" + ip; if (jedis.exists(key)) { long afterValue = jedis.incr(key); if (afterValue > limit) { result = false; } } else { Transaction transaction = jedis.multi(); transaction.incr(key); transaction.expire(key, time); transaction.exec(); } return result; }
以上代碼有兩點(diǎn)缺陷
可能會(huì)出現(xiàn)競(jìng)態(tài)條件: 解決方法是用 WATCH 監(jiān)控 rate.limit:$IP 的變動(dòng), 但較為麻煩;以上代碼在不使用 pipeline 的情況下最多需要向Redis請(qǐng)求5條指令, 傳輸過(guò)多.
Lua腳本實(shí)現(xiàn)
Redis 允許將 Lua 腳本傳到 Redis 服務(wù)器中執(zhí)行, 腳本內(nèi)可以調(diào)用大部分 Redis 命令, 且 Redis 保證腳本的原子性:
首先需要準(zhǔn)備Lua代碼: script.lua
-- -- Created by IntelliJ IDEA. -- User: jifang -- Date: 16/8/24 -- Time: 下午6:11 -- local key = "rate.limit:" .. KEYS[1] local limit = tonumber(ARGV[1]) local expire_time = ARGV[2] local is_exists = redis.call("EXISTS", key) if is_exists == 1 then if redis.call("INCR", key) > limit then return 0 else return 1 end else redis.call("SET", key, 1) redis.call("EXPIRE", key, expire_time) return 1 end
Java
private boolean accessLimit(String ip, int limit, int timeout, Jedis connection) throws IOException { Listkeys = Collections.singletonList(ip); List argv = Arrays.asList(String.valueOf(limit), String.valueOf(timeout)); return 1 == (long) connection.eval(loadScriptString("script.lua"), keys, argv); } // 加載Lua代碼 private String loadScriptString(String fileName) throws IOException { Reader reader = new InputStreamReader(Client.class.getClassLoader().getResourceAsStream(fileName)); return CharStreams.toString(reader); }
Lua 嵌入 Redis 優(yōu)勢(shì):
減少網(wǎng)絡(luò)開(kāi)銷(xiāo): 不使用 Lua 的代碼需要向 Redis 發(fā)送多次請(qǐng)求, 而腳本只需一次即可, 減少網(wǎng)絡(luò)傳輸;原子操作: Redis 將整個(gè)腳本作為一個(gè)原子執(zhí)行, 無(wú)需擔(dān)心并發(fā), 也就無(wú)需事務(wù);復(fù)用: 腳本會(huì)永久保存 Redis 中, 其他客戶(hù)端可繼續(xù)使用。
以上是“redis能夠采用什么樣的方式來(lái)實(shí)現(xiàn)限流”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!