Maison >base de données >Redis >Comment Redis peut-il implémenter la limitation de courant ?

Comment Redis peut-il implémenter la limitation de courant ?

王林
王林avant
2021-01-20 09:16:572193parcourir

Comment Redis peut-il implémenter la limitation de courant ?

Objectif :

  • Atteindre la limite de fréquence d'accès

  • Atteindre le $ip des visiteurs dans une certaine limite Vous ne pouvez accéder à $limit times que dans le délai $time

(Partage de vidéos d'apprentissage : tutoriel vidéo Redis)

Implémentation sans script

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; }

Le code ci-dessus a deux défauts

Une condition de concurrence critique peut survenir : la solution est d'utiliser WATCH pour surveiller les changements dans rate.limit:$IP, mais c'est plus gênant ; Le code ci-dessus n'utilise pas de pipeline. Dans ce cas, jusqu'à 5 instructions doivent être demandées à Redis, ce qui est trop important à transmettre

Implémentation du script Lua

Redis autorise les scripts Lua. à transférer sur le serveur Redis pour exécution, et peut être appelé dans le script La plupart des commandes Redis, et Redis garantit l'atomicité des scripts :

Vous devez d'abord préparer le code 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 { 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 Embed Redis Avantages :

Réduisez la surcharge du réseau : le code qui n'utilise pas Lua doit envoyer plusieurs requêtes à Redis, mais le script doit seulement être envoyé une seule fois, réduisant la transmission réseau ; opérations atomiques : Redis exécute l'intégralité du script de manière atomique, pas besoin de s'inquiéter. La concurrence signifie qu'il n'y a pas besoin de réutilisation : le script sera enregistré de manière permanente dans Redis et les autres clients pourront continuer à l'utiliser ; .

Recommandations associées : Tutoriel sur la base de données Redis

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer