Heim  >  Artikel  >  Datenbank  >  Wie kann Redis eine Strombegrenzung implementieren?

Wie kann Redis eine Strombegrenzung implementieren?

王林
王林nach vorne
2021-01-20 09:16:572153Durchsuche

Wie kann Redis eine Strombegrenzung implementieren?

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-Tutorial

Das 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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen