码迷,mamicode.com
首页 > 其他好文 > 详细

如何使用redis计数器防止并发请求

时间:2018-12-30 02:50:03      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:redis   序列   需要   序列号   防止   解决   stat   时间差   通过   

需求描述

      最近项目中有个需求,短信发送的并发请求问题:业务需求是需要限制一个号码一分钟内只能获取一次随机码,之前的实现是短信发送请求过来后,先去数据库查询发送记录,根据上一次的短信发送时间和当前时间比较,如果时间差小于一分钟,则提示短信获取频繁,如果超过一分钟,则发送短信,并记录短信发送日志。

 

问题分析

      短信发送是一个很敏感的业务,上面的实现存在一个并发请求的问题,当同一时间有很多请求过来时,同时去查库,同时获取到上一次发送时间没有,或者已超过一分钟,这时候就会重复发送短信了。

 

使用Redis incr解决问题

      Redis incr 可以实现原子性的递增,可应用于高并发的秒杀活动、分布式序列号生成等场景。这里我使用它来计数实现一分钟内只接受一次请求。

 

      实现逻辑也很简单:我们在接到短信发送请求后,使用Redis的incr设置一个递增KEY(KEY由固定字符串+手机号码组成),并判断该KEY的数值,如果等于1,说明是第一个请求,我们将该KEY值有效期设置为一分钟;如果该KEY的数值大于1,说明是1分钟内的多次请求,这时我们直接返回短信获取频繁,代码如下:

<?php

$redis = new Redis();
$redis->connect(‘127.0.0.1‘, 6379);

$tel = ‘13250206603‘;
$redisKey = "SMS_LIMIT_" + $tel;
$count = $redis->incr($redisKey,1);
if ($count == 1) {
//设置有效期10s
$redis->expire($redisKey, 10); 
}
if ($count > 1) {
    $time = $redis->ttl($redisKey); //返回有效期值1s
    echo $time;//输出剩余秒杀
    if($time == 0){
        $redis->expire($redisKey); //取消expire行为
    }
    echo json_encode([‘status‘=>404]);
    return;
}
/** 发送短信 */
echo json_encode([‘status‘=>200]);
/** 记录发送日志 */

测试

      使用Jmeter进行并发测试,同时发送100个线程请求,通过测试发现可避免并发请求问题 :

技术分享图片

查看结果,只有第一个请求发送了短信,剩余99个请求均返回失败:

技术分享图片

技术分享图片

 

 

参考:https://mp.weixin.qq.com/s/_e7g1tmhE2Hd0whoWLWCMQ

如何使用redis计数器防止并发请求

标签:redis   序列   需要   序列号   防止   解决   stat   时间差   通过   

原文地址:https://www.cnblogs.com/clubs/p/10198250.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!