La commande EXINCRBY de TairString applique des limites supérieures et inférieures strictes de manière atomique, sans nécessiter de scripts Lua pour les cas simples. Cette fonctionnalité est idéale pour le suivi des stocks lors de ventes flash et la limitation du débit, où le dépassement d'un seuil a des conséquences réelles.
Fonctionnement
Les commandes EXINCRBY et EXINCRBYFLOAT étendent les commandes natives Redis INCRBY et INCRBYFLOAT en ajoutant des options supplémentaires, notamment MIN et MAX :
| Option | description |
|---|---|
MIN |
Rejette l'opération si le résultat est inférieur à cette valeur |
MAX |
Rejette l'opération si le résultat dépasse cette valeur |
EX |
Définit l'expiration en secondes |
NX |
Définit la valeur uniquement si la clé n'existe pas |
VER |
Vérification de version pour le verrouillage optimiste |
KEEPTTL |
Conserve le TTL existant |
Lorsque la limite est violée, EXINCRBY renvoie "increment or decrement would overflow" au lieu de mettre à jour la clé. Traitez cette réponse comme un signal indiquant qu'il faut cesser d'accepter la requête ; aucune vérification secondaire n'est nécessaire.
Chaque appel à EXINCRBY est atomique. Il n'y a aucune fenêtre temporelle entre la lecture et l'écriture durant laquelle deux requêtes concurrentes pourraient voir la même valeur restante.
TairString prend en charge toutes les fonctionnalités natives des chaînes Redis, à l'exception des opérations sur les bits.
Pour la référence complète des commandes, consultez Commandes TairString.
Quand utiliser des compteurs bornés
Utilisez EXINCRBY avec MIN/MAX lorsque vous avez besoin d'un seuil strict qui ne doit jamais être franchi :
| Scénario | Approche | Pourquoi les compteurs bornés sont adaptés |
|---|---|---|
| Stock pour vente flash | Décrémenter avec MIN 0 |
Le stock ne peut jamais descendre en dessous de zéro ; aucune survente possible |
| Plafond de requêtes concurrentes | Incrémenter avec MAX N |
Les requêtes actives ne peuvent jamais dépasser N |
| Limitation des tentatives de connexion | Incrémenter avec MAX N + EX |
La limite se réinitialise après l'expiration de la fenêtre |
| Limitation du taux de changement de mot de passe | Incrémenter avec MAX N + EX |
Empêche le bourrage d'identifiants au niveau du compteur |
Comparaison avec INCRBY natif de Redis utilisant Lua : Les chaînes natives nécessitent un script Lua pour lire, comparer et mettre à jour conditionnellement en une seule étape atomique. EXINCRBY gère cette opération via une seule commande, ce qui réduit la complexité du code et les allers-retours réseau. Utilisez les chaînes natives avec Lua si vous avez besoin d'une logique conditionnelle plus complexe qui va au-delà d'un seuil min/max fixe.
Contrôle des stocks pour les ventes flash
Pour éviter les surventes, définissez le stock initial comme valeur TairString et décrémentez-le avec MIN 0. Une fois le stock arrivé à zéro, EXINCRBY rejette automatiquement les décrémentations suivantes.
if(EXINCRBY(key_iphone, -1, MIN:0) == "would overflow")
run_out();
Limitation du débit et throttling
Utilisez MAX pour plafonner le compteur à une limite supérieure. L'exemple suivant limite les requêtes concurrentes à 1 000 :
if(EXINCRBY(rate_limitor, 1, MAX:1000) == "would overflow")
traffic_control();
Ce modèle s'applique à tout scénario comportant un seuil numérique : requêtes par seconde (QPS), connexions simultanées, tentatives de connexion ou fréquence de changement de mot de passe.
Exemple Java : limiteur de requêtes concurrentes
La méthode tryAcquire suivante est thread-safe. Elle incrémente le compteur dans une fenêtre d'expiration et renvoie false une fois la limite supérieure atteinte.
/**
* Attempts to acquire a slot within the rate limit window.
*
* @param key The rate limit key
* @param upperBound The maximum allowed count
* @param interval The time window in seconds
* @return true if the slot was acquired; false if the limit is reached
*/
public static boolean tryAcquire(String key, int upperBound, int interval) {
try (Jedis jedis = jedisPool.getResource()) {
jedis.eval("if redis.call('exists', KEYS[1]) == 1 "
+ "then return redis.call('EXINCRBY', KEYS[1], '1', 'MAX', ARGV[1], 'KEEPTTL') "
+ "else return redis.call('EXSET', KEYS[1], 0, 'EX', ARGV[2]) end",
Arrays.asList(key), Arrays.asList(String.valueOf(upperBound), String.valueOf(interval)));
return true;
} catch (Exception e) {
if (e.getMessage().contains("increment or decrement would overflow")) {
return false;
}
e.printStackTrace();
}
return false;
}
Le script Lua combine deux opérations de manière atomique :
Si la clé existe : incrémenter avec
EXINCRBY, en appliquantMAXet en conservant le TTL existant avecKEEPTTL.Si la clé n'existe pas : l'initialiser à
0avecEXSETet définir la fenêtre d'expiration avecEX.
Gestion des échecs en production : La méthode tryAcquire traite le dépassement de capacité comme un signal de contrôle de flux attendu. Pour les autres exceptions, telles qu'une échec de connexion Redis, la méthode consigne actuellement l'erreur et renvoie false, ce qui bloque les requêtes (fail closed). Décidez si votre application doit autoriser les requêtes (fail open) ou les bloquer (fail closed) lorsque TairString est indisponible, et mettez à jour le gestionnaire d'exceptions en conséquence.
Étapes suivantes
Commandes TairString — Référence complète pour
EXINCRBY,EXINCRBYFLOAT,EXSETet toutes les options prises en charge