Maison  >  Article  >  développement back-end  >  Explication détaillée de la structure de données de type liste de PHP basée sur Redis pour implémenter l'opération de limitation de courant IP

Explication détaillée de la structure de données de type liste de PHP basée sur Redis pour implémenter l'opération de limitation de courant IP

藏色散人
藏色散人avant
2021-02-09 09:06:293339parcourir

Recommandé : "Tutoriel vidéo PHP"

Dans le développement quotidien de fonctions métier, si vous souhaitez restreindre n'importe quelle adresse IP à un accès uniquement pendant une certaine période de temps Comment mettre en œuvre une certaine interface un certain nombre de fois ?
Cette exigence fonctionnelle est généralement utilisée pour empêcher les scripts de brosser les interfaces de manière malveillante. Actuellement, il existe de nombreuses solutions de limitation actuelles relativement complètes sur Internet. Pour les sites généraux, vous pouvez utiliser la structure de données de liste chaînée de redis pour implémenter la fonction de limitation de courant IP.
Par exemple -
Supposons que nous devions implémenter, pour l'interface A, limiter toute adresse IP pour autoriser jusqu'à 3 accès toutes les 5 secondes consécutives. Si plus de 3 fois, une erreur sera renvoyée.
Explication détaillée de la structure de données de type liste de PHP basée sur Redis pour implémenter lopération de limitation de courant IP
Pour l'image ci-dessus, à 08 secondes, 4 requêtes ont été initiées au cours des 5 dernières secondes, ce qui a atteint la limite maximale en nombre, l'accès sera donc restreint à ce moment.
S'il est implémenté en PHP, le code logique spécifique est le suivant -

/**
* 检查队列的长度是否到达设定的阈值,已到达则返回false,未到达则将当前时间戳推入队列最末端,同时刷新队列整体的缓存时间
* @param $key 队列缓存的key
* @param $expire 队列缓存过期时间,例如上面例子中的5秒
* @param $limit 队列长度阈值,如上面例子中的3次
* @return bool
*/public function checkLimit($key, $expire, $limit){
    $length = $this->refreshList($key, $expire);
    if ($length rPush($key, time());
        $this->expire($key, intval($limit));
        return true;
    }
    return false;}/** 
* 刷新队列,过滤掉已经不在有效时间内的值,返回最新队列的长度
* @param $key string 自定义的缓存key
* @param $expire 队列缓存过期时间,例如上面例子中的5秒
* @return bool|int
*/public function refreshList ($key, $expire)   
 {
        if ($this->has($key)) {
            do { // 对于已存在数据的list,要先从前往后把已经过期的数据弹出
                $oldest_value = $this->lPop($key);
            } while ($oldest_value && time() - $oldest_value > $expire);
            // 把最后弹出的数据重新塞回list的最前边
            $oldest_value && $this->lPush($key, $oldest_value);
            return $this->lLen($key);
        }
        return 0;}

Le lPop, lPush, lLen, rPush et les autres méthodes utilisées sont toutes encapsulées après l'expansion de Redis, certaines méthodes d'exploitation des structures de données, des paramètres et des valeurs de retour de listes chaînées sont cohérentes avec les méthodes natives.
En fait, j'ai découvert plus tard après avoir vérifié en ligne que Redis gère ce scénario plus directement en utilisant un ensemble ordonné comme zset. La logique est fondamentalement la même, qui consiste à stocker l'horodatage actuel puis à utiliser l'algorithme de fenêtre glissante. L'idée est de déterminer si la longueur de la valeur dans la fenêtre actuelle a dépassé la limite.

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