Maison > base de données > Redis > Fréquence de fonctionnement de la limite de combat réelle Redis

Fréquence de fonctionnement de la limite de combat réelle Redis

步履不停
Libérer: 2019-06-26 17:00:16
original
2807 Les gens l'ont consulté

Fréquence de fonctionnement de la limite de combat réelle Redis

Je suis récemment obsédé par le développement commercial et je n'ai pas mis à jour mon blog depuis un certain temps. Je prévois d'inclure des solutions pratiques dans des scénarios commerciaux ou de meilleures idées de conception dans les prochaines années. Partager des articles de blog, ce n'est pas comme passer beaucoup de temps à trier du contenu lié à un sujet auparavant (retenir l'astuce ultime). Le contenu de l'article suivant n'est peut-être pas aussi riche, mais il peut être plus détaillé sur un point. autant que possible, ou Analyse plus approfondie, grâce au partage continu et à l'auto-évaluation, à l'accumulation d'expériences, tout en augmentant la fréquence de partage de blogs

Scénario

Scénario 1

留言功能限制,30秒 内只能评论 10次,超出次数不让能再评论,并提示:过于频繁
Copier après la connexion

Scénario 2

点赞功能限制,10秒 内只能点赞 10次,超出次数后不能再点赞,并禁止操作 1个小时,提示:过于频繁,被禁止操作1小时
Copier après la connexion

Scénario 3

上传记录功能,限制一天只能上传 100次,超出次数不让能再上传,并提示:超出今日上线
Copier après la connexion

Résumer de l'essence

Dans le processus de développement commercial, nous sommes constamment impliqués dans la conception de divers scénarios commerciaux, et il est souvent facile de rencontrer des scénarios de solutions très similaires, mais les modules métier actuels auxquels ils appartiennent sont différents. En fait, l'essence de ces exigences est de résoudre le même problème. Lorsque nous rencontrons ce scénario, nous devons en extraire les problèmes essentiels. les exigences basées sur notre propre expérience, analysent et mettent en œuvre des solutions universelles, rendent vos solutions plus précieuses, cela peut faire la différence entre vous êtes un ingénieur avec une âme ou le roi du cp (copier-coller) le plus fort.

En analysant les trois scénarios commerciaux ci-dessus, nous pouvons constater qu'ils contiennent une logique similaire, les appelant des problèmes similaires. Nous allons maintenant résumer ce problème, concevoir une solution générale et décrire le même organigramme logique. :

Fréquence de fonctionnement de la limite de combat réelle Redis

En analysant les scénarios de demande ci-dessus, nous pouvons extraire les conditions dont ils ont tous besoin :

Objets restreints : opérations restreintes par les utilisateurs (commentaires, likes), record, ...) Le nombre d'opérations dans la plage de temps

(最小时间单位用秒:天/小时/分钟都可换算成秒,用秒可以解决更多的场景)
Copier après la connexion

Si la fonction est extraite dans une fonction générale, ressemblerait-elle à ceci :

<?php/**
 * 频率限制
 * @param string $action 操作动作
 * @param int $userId 发起操作的用户ID
 * @param int $time 时间范围X秒内
 * @param int $number 限制操作数Y次
 * @param array $expire 超出封印时间Z [&#39;type&#39;=>1,&#39;ttl&#39;=>过期时间/秒] [&#39;type&#39;=>2,&#39;ttl&#39;=>具体过期时间戳] 二选一
 * @return bool
 * @throws \Exception
 */public static function frequencyLimit(string $action, int $userId, int $time, int $number, $expire = []){    // todo 根据用户操作动作时间范围,进行频率的控制和失效释放}
Copier après la connexion
Fréquence de fonctionnement de la limite de combat réelle RedisPour implémenter la solution

La fonction doit effectuer les opérations et le temps initiés par l'utilisateur, ainsi que le nombre cumulé de stockage, et doit nettoyer l'expiration si nous comptons sur MySQL pour le stockage à ce moment-là, ce sera assez pénible. pour y réfléchir.Le protagoniste ici : redis apparaît enfin. Sur la base des caractéristiques de redis, le fonctionnement atomique de incr et key prend en charge le mécanisme d'expiration et le stockage en mémoire. L'avantage en termes d'efficacité peut atteindre l'objectif de manière relativement simple, flexible et efficace.

Voici un code qui implémente simplement une fonction commune :

<?php/**
 * 频率限制
 * @param string $action 操作动作
 * @param int $userId 发起操作的用户ID
 * @param int $time 时间范围X秒内
 * @param int $number 限制操作数Y次
 * @param array $expire  超出封印时间Z [&#39;type&#39;=>1,&#39;ttl&#39;=>过期时间/秒] [&#39;type&#39;=>2,&#39;ttl&#39;=>具体过期时间戳] 二选一
 * @return bool
 * @throws \Exception
 */public function frequencyLimit(string $action, int $userId, int $time, int $number, $expire = []){    if (empty($action) || $userId <= 0 || $time <= 0 || $number <= 0) {        throw new \Exception(&#39;非法参数&#39;);
    }
    $key = &#39;act:limit:&#39; . $action . &#39;:&#39; . $userId;
    $r = RedisClient::connect();    //获取当前累计次数
    $current = intval($r->get($key));    if ($current >= $number) return false;    //累计并返回最新值
    $current = $r->incr($key);    //第一次累加,设置控制操作频率的有效时间
    if ($current === 1) $r->expire($key, $time);    //未超出限制次数先放过
    if ($current < $number) return true;    //超出后根据需要重新设置过期失效时间 $current === $number 判断保证只重新设置一次
    $type = empty($expire[&#39;type&#39;]) ? 0 : intval($expire[&#39;type&#39;]);
    $ttl = empty($expire[&#39;ttl&#39;]) ? 0 : intval($expire[&#39;ttl&#39;]);    if ($current === $number && $ttl > 0 && in_array($type, [1, 2])) {        if ($type === 1) $r->expire($key, $ttl);        if ($type === 2) $r->expireAt($key, $ttl);
    }    return false;
}//场景1/**
 * 评论限制
 * @param int $userId
 * @return bool|string
 */public function doComment(int $userId){    try {
        $pass = FrequencyLimit::doHandle(&#39;comment&#39;, $userId, 30, 10);        if (!$pass) return &#39;过于频繁&#39;;        // todo 评论逻辑
        return true;
    } catch (\Exception $e) {        return $e->getMessage();
    }
}//场景2/**
 * 点赞限制
 * @param int $userId
 * @return bool|string
 */public function doLike(int $userId){    try {
        $pass = FrequencyLimit::doHandle(&#39;like&#39;, $userId, 10, 10, [&#39;type&#39; => 1, &#39;ttl&#39; => 1 * 60 * 60]);        if (!$pass) return &#39;过于频繁,被禁止操作1小时&#39;;        // todo 点赞逻辑
        return true;
    } catch (\Exception $e) {        return $e->getMessage();
    }
}//场景3/**
 * 上传限制
 * @param int $userId
 * @return bool|string
 */public function doUpload(int $userId){    try {
        $expire = strtotime(date(&#39;Y-m-d&#39;, strtotime(+1 . &#39;days&#39;)));
        $pass = FrequencyLimit::doHandle(&#39;upload&#39;, $userId, 1 * 24 * 60 * 60, 100, [&#39;type&#39; => 2, &#39;ttl&#39; => $expire]);        if (!$pass) return &#39;超出今日上线&#39;;        // todo 上传逻辑
        return true;
    } catch (\Exception $e) {        return $e->getMessage();
    }
}//场景N
Copier après la connexion
编码上可以根据你设计这个通用方案的复杂度进行进一步抽象,如抽象成频率限制的功能类等
Copier après la connexion

Résumé

Analyser des scénarios commerciaux similaires, découvrir des problèmes essentiels et concevoir des solutions générales

Faire des solutions plus précieuses et soyez un développeur avec une âme

Maîtrisez Redis et utilisez pleinement ses fonctionnalités et avantages

Pour plus d'articles techniques liés à Redis, veuillez visiter

Tutoriel Redis

colonne pour apprendre !

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:php.cn
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