Zweck:
Um eine Zugriffshäufigkeitsbeschränkung zu erreichen
Um zu erreichen, dass Besucher $ip nur $limit-Zeiten innerhalb einer bestimmten Zeit $time zugreifen können
(Teilen von Lernvideos: redis-Video-Tutorial )
Nicht-Skript-Implementierung
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; }
Der obige Code weist zwei Mängel auf
Es kann zu Race-Bedingungen kommen: Die Lösung besteht darin, WATCH zu verwenden, um rate.limit:$IP-Änderungen zu überwachen, aber es ist problematischer; Code verwendet keine Pipeline. In diesem Fall müssen bis zu 5 Anweisungen von Redis angefordert werden, was zu viel ist, um sie zu übertragen.
Redis ermöglicht die Übertragung von Lua-Skripten zur Ausführung auf den Redis-Server Redis-Befehle können im Skript aufgerufen werden, und Redis stellt sicher, dass das Skript Atomicity:
Zuerst müssen Sie Lua-Code vorbereiten: 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 { List<String> keys = Collections.singletonList(ip); List<String> 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 Einbettung von Redis Vorteile:
Reduzierter Netzwerk-Overhead: Codes Diejenigen, die Lua nicht verwenden, müssen mehrere Anfragen an Redis senden, aber das Skript benötigt nur einmal, wodurch die Netzwerkübertragung reduziert wird. Atomare Operation: Redis führt das gesamte Skript als atomare Operation aus, ohne sich um die Parallelität zu kümmern, und es sind keine Transaktionen erforderlich ; Wiederverwendung: Das Skript wird dauerhaft in Redis gespeichert und kann von anderen Clients weiterhin verwendet werden.
Verwandte Empfehlungen:
Redis-Datenbank-TutorialDas obige ist der detaillierte Inhalt vonWie kann Redis eine Strombegrenzung implementieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!