thinkphp:redis+lua实现短信发送频率限制(thinkphp v6.0.12LTS)
Redis 实现 发送 限制 lua thinkphp 短信 频率
2023-09-14 08:59:32 时间
一,配置:
.env中
[REDIS0] TYPE = redis HOST = 127.0.0.1 PORT = 6379 PASSWORD =
二,php代码:
1,lib\util\SmsRateUtil.php
<?php namespace app\lib\util; //短信验证码发送频率 class SmsRateUtil { //redis连接 private $redis; //60秒内不允许重复发送 private $sendSeconds = "60"; //一天内最多发10条 private $dayCount = "10"; //构造 public function __construct($redis){ $this->redis = $redis; } /* 用lua脚本实现访问redis保存访问次数 KEYS[1] : 主键,此处是手机号 KEYS[2] : 主键过期的秒数,如果主键存在,表示不允许再次发送 KEYS[3]: 每手机号每天时间内最多允许发送的条数 */ function setRate($mobile) { $lua = <<<SCRIPT local key = KEYS[1] local keyseconds = tonumber(KEYS[2]) local daycount = tonumber(KEYS[3]) local keymobile = 'SmsAuthKey:'..key local keycount = 'SmsAuthCount:'..key --redis.log(redis.LOG_NOTICE,' keyseconds: '..keyseconds..';daycount:'..daycount) local current = redis.call('GET', keymobile) --redis.log(redis.LOG_NOTICE,' current: keymobile:'..current) if current == false then --redis.log(redis.LOG_NOTICE,keymobile..' is nil ') local count = redis.call('GET', keycount) if count == false then redis.call('SET', keycount,1) redis.call('EXPIRE',keycount,86400) redis.call('SET', keymobile,1) redis.call('EXPIRE',keymobile,keyseconds) return '1' else local num_count = tonumber(count) if num_count+1 > daycount then return '2' else redis.call('INCRBY',keycount,1) redis.call('SET', keymobile,1) redis.call('EXPIRE',keymobile,keyseconds) return '1' end end else --redis.log(redis.LOG_NOTICE,keymobile..' is not nil ') return '0' end SCRIPT; $key = $mobile; //执行lua脚本 $sequence = $this->redis->eval($lua, [$key,$this->sendSeconds,$this->dayCount], 3); //检查是否出错 $luaError = $this->redis->getLastError(); if (isset($luaError)) { // print_r($luaError); } //返回 return $sequence; } }
2,从controller中调用:
class Sms extends BaseController { //redis连接 private $redis; //构造 public function __construct(App $app = null){ //继承父类的构造方法 parent::__construct($app); //创建连接 $redis = new \Redis(); $port = env('redis0.port', '6379'); $port = intval($port); $redis->connect(env('redis0.host', '127.0.0.1'),$port); $redis->select(0); $this->redis = $redis; } //判断是否可以发送短信验证码 public function rate() { //得到参数 $mobile = $this->request->param('mobile','','string'); echo "mobile:".$mobile.":<br/>"; //判断是否可以发送 $rate = new SmsRateUtil($this->redis); $ret = $rate->setRate($mobile); echo "ret:".$ret.":<br/>"; //返回的说明信息 $res = ""; if ($ret == '1') { $res = "可以发短信"; } else if ($ret == '0') { $res = "请超过60秒之后再发短信"; } else if ($ret == '2') { $res = "当前手机号本日内发送数量已超限制"; } else { $res = "发生错误"; } echo "res:".$res.":<br/>"; }
三,测试效果
说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
四,查看thinkphp的版本:
liuhongdi@lhdpc:/data/php/imgtouch$ php think version v6.0.12LTS
相关文章
- 强大的 Redis 群集: 无与伦比的性能(redis群集)
- 控制实现Redis读写权限控制的方法(redis读写权限)
- 认识Redis——理解数据量上限(redis数量上限)
- 使用 Redis 实现分布式 ID 生成方案(redis分布式id)
- 实现Java实现Redis入门指南(redis入门Java)
- 数据存储虚拟机储存Redis数据的利与弊(虚拟机redis)
- Redis 实现的分库技术研究(redis分库)
- 提高性能通过Redis改善IP复用(得便redis改ip)
- 如何解决电脑Redis服务无法启动问题(电脑redis无法启动)
- 极速提取Redis数据,开启新高效之旅(提取redis)
- 消息向Redis传递信息让网络更加便捷(向redis发送)
- Redis集群逐步掌握Scan的用法(redis集群里scan)
- 架构设计基于Redis的集群实现(redis集群架构实现)
- 深入浅出Redis集群实现的机制(redis集群实现原理)
- Redis集群实现多台机器的协作(redis集群 多台机器)
- Redis重启重新装载数据(redis重启装载数据)
- 维护Redis连接,实现保活状态(redis连接保活)
- 基于Redis实现快速键值对存储(redis 设置键值)
- Redis获取钥匙揭开简单之门(redis 获得key)