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 ?

王林
Libérer: 2021-01-20 09:16:57
avant
2216 Les gens l'ont consulté

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; }
Copier après la connexion

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
Copier après la connexion

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); }
Copier après la connexion

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!

Étiquettes associées:
source:csdn.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal