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

需求描述

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

问题分析

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

使用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

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

时间: 2024-10-11 16:34:33

如何使用redis计数器防止并发请求的相关文章

Redis原子计数器incr,防止并发请求

转自:https://blog.csdn.net/Roy_70/article/details/78260826 一.前言在一些对高并发请求有限制的系统或者功能里,比如说秒杀活动,或者一些网站返回的当前用户过多,请稍后尝试.这些都是通过对同一时刻请求数量进行了限制,一般用作对后台系统的保护,防止系统因为过大的流量冲击而崩溃.对于系统崩溃带来的后果,显然还是拒绝一部分请求更能被维护者所接受. 而在各种限流中,除了系统自身设计的带锁机制的计数器外,利用Redis实现显然是一种既高效安全又便捷方便的方

IIS处理并发请求时出现的问题及解决

原文链接:http://www.cnblogs.com/hgamezoom/p/3082538.html 一个ASP.NET项目在部署到生产环境时,当用户并发量达到200左右时,IIS出现了明显的请求排队现象,发送的请求都进入等待,无法及时响应,系统基本处于不可用状态.因经验不足,花了很多时间精力解决这个问题,本文记录了我查找问题的过程和最后解决方案,供大家参考. 软硬件环境: IBM刀片服务器,Intel至强处理器,4物理核,16个逻辑核心,内存32G Windows Server2008 E

Redis实现高并发分布式序列号

使用Redis实现高并发分布式序列号生成服务 序列号的构成 为建立良好的数据治理方案,作数据掌握.分析.统计.商业智能等用途,业务数据的编码制定通常都会遵循一定的规则,一般来讲,都会有自己的编码规则和自增序列构成.比如我们常见的身份证号.银行卡号.社保电脑号等等. 以某公司产品标识码(代表该产品的唯一编码)的构成为例: 规则定义:商品款号(8位)+颜色号(3位)+号型码(3位) (共14位) 其标识码为:62X19001 001 46A 业务含义为: 2009年男装秋冬季仿毛套西黑色170A版

nginx+lua+redis构建高并发应用(转)

nginx+lua+redis构建高并发应用 ngx_lua将lua嵌入到nginx,让nginx执行lua脚本,高并发,非阻塞的处理各种请求. url请求nginx服务器,然后lua查询redis,返回json数据. 备注:centos或者redhat系统请跳转到nginx + ngx_lua安装测试 一.安装lua 1 2 3 # apt-get install lua5.1 # apt-get install liblua5.1-dev # apt-get install liblua5.

测算Redis处理实际生产请求的QPS/TPS

测算Redis处理实际生产请求的QPS/TPS Benchmark工具 redis发布版本中自带了redis-benchmark性能测试工具; 示例: 使用50个并发连接,发出100000个请求,每个请求的数据为2kb, 测试host为127.0.0.1 端口为6379的redis服务器性能: ./redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 100000 -d 2 ... ====== SADD ====== 100000 requests com

(实例篇)php 使用redis锁限制并发访问类示例

1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券. 伪代码如下: if A(可以换领)         B(执行换领)              C(更新为已换领)             D(结束) 如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会

如何配置IIS处理多并发请求及存在的问题

很多时候多线程能快速高效独立的计算数据,应用比较多. 但今天遇到的多进程下的问题更是让人觉得复杂 多进程下static变量都要失效,就目前的平台和产品static使用是很多的,各种session.cache等,完全不适合多进程. 分布式系统之间不能相互使用进程内的变量,必须使用分布式缓存之类的远程容器,否则无法做到跨进程. 同样的Application变量也没法使用,必须做进程间通信. 分布式系统比普通系统复杂得多的,支持几千人在线的系统和支持数十万人在线的系统的架构是不同的. so,面对如此多

php 使用redis锁限制并发访问类

1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券. 伪代码如下: if A(可以换领) B(执行换领) C(更新为已换领) D(结束) 如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C).因此如果用户在有一个更新为已换领之前,有多少次

Nginx与Redis解决高并发问题

原文链接:http://bbs.phpchina.com/forum.php?mod=viewthread&tid=229629 第一版产品采用的是Jquery,Nginx,PHP(CI框架),Memcache,Mysql这种常用的架构.作为一名PHP工程师对于这种架构已经非常的熟悉了,目前站点并发并不是很高,线上环境使用的是阿里云主机,1.5G的内存,PHP并发能支持400~500左右.因为使用memcache的原因,如果在并发特别高的情况下,除了带宽瓶颈以外就可能会是一直引以为傲PHP瓶颈了