
最近沉迷于业务开发无法自拔 ,有一段时间没有更新博文了,后续博文内容计划把一些业务场景下的实战方案,或者比较好的设计思路进行分享,就不像之前围绕着一个主题,消耗很多的时间去整理相关内容(憋大招),后续可能一篇的内容量就没那么丰富,但是尽可能针对一个点进行更细化,或者更深入的分析,通过不断分享和自我复盘,进行经验的沉淀,同时提高博文分享的频率
场景
场景1
留言功能限制,30秒 内只能评论 10次,超出次数不让能再评论,并提示:过于频繁
场景2
点赞功能限制,10秒 内只能点赞 10次,超出次数后不能再点赞,并禁止操作 1个小时,提示:过于频繁,被禁止操作1小时
场景3
上传记录功能,限制一天只能上传 100次,超出次数不让能再上传,并提示:超出今日上线
抽离本质
在业务开发的过程中,我们不断的参与各种业务场景的方案设计,往往很容易碰到很类似的场景,只不过当前所属的业务模块不一样,其实这些需求的本质是解决同一个问题,当遇到这种场景的时候,我们需要根据自己经验分析抽离出需求的本质问题,实现一个通用的解决方案,让自己的解决方案更有价值,这可能就是区别于你是有灵魂的工程师还是cp(copy paste)最强王者吧。
分析上面3个业务场景,可以从中发现其中有相似的逻辑,称它为同类的问题,现在我们就是要抽离这个问题,设计一个通用的解决方案,勾画相同逻辑流程图:

通过分析上面的需求场景,抽离出他们都需要的那些条件:
限制对象:用户限制操作(评论,点赞,记录, ...)时间范围X秒内限制操作数Y次超出后禁止操作时间Z(秒/具体时间)超出后不让再操作,并提示

白瓜面试
白瓜面试 - AI面试助手,辅助笔试面试神器
162
查看详情
(最小时间单位用秒:天/小时/分钟都可换算成秒,用秒可以解决更多的场景)
如果把功能抽离成一个通用函数是不是大概是这样:
<?php/**
* 频率限制
* @param string $action 操作动作
* @param int $userId 发起操作的用户ID
* @param int $time 时间范围X秒内
* @param int $number 限制操作数Y次
* @param array $expire 超出封印时间Z ['type'=>1,'ttl'=>过期时间/秒] ['type'=>2,'ttl'=>具体过期时间戳] 二选一
* @return bool
* @throws \Exception
*/public static function frequencyLimit(string $action, int $userId, int $time, int $number, $expire = []){ // todo 根据用户操作动作时间范围,进行频率的控制和失效释放}解决方案落地
功能中需要对用户发起的操作和时间,以及累计次数进行存储,并且需要失效过期的清理,如果这个时候我们依赖mysql做存储,想想都觉的挺痛苦,这里主角:redis 终于登场了,基于redis特性,incr的原子操作和key 支持过期机制,内存存储的效率优势,可以相对简单灵活并且又高效的完成目的。
这里简单实现个通用功能的代码:
<?php/**
* 频率限制
* @param string $action 操作动作
* @param int $userId 发起操作的用户ID
* @param int $time 时间范围X秒内
* @param int $number 限制操作数Y次
* @param array $expire 超出封印时间Z ['type'=>1,'ttl'=>过期时间/秒] ['type'=>2,'ttl'=>具体过期时间戳] 二选一
* @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('非法参数');
}
$key = 'act:limit:' . $action . ':' . $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['type']) ? 0 : intval($expire['type']);
$ttl = empty($expire['ttl']) ? 0 : intval($expire['ttl']); 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('comment', $userId, 30, 10); if (!$pass) return '过于频繁'; // 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('like', $userId, 10, 10, ['type' => 1, 'ttl' => 1 * 60 * 60]); if (!$pass) return '过于频繁,被禁止操作1小时'; // 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('Y-m-d', strtotime(+1 . 'days')));
$pass = FrequencyLimit::doHandle('upload', $userId, 1 * 24 * 60 * 60, 100, ['type' => 2, 'ttl' => $expire]); if (!$pass) return '超出今日上线'; // todo 上传逻辑
return true;
} catch (\Exception $e) { return $e->getMessage();
}
}//场景N编码上可以根据你设计这个通用方案的复杂度进行进一步抽象,如抽象成频率限制的功能类等
总结
对相似的业务场景进行分析,发现本质问题并设计通用的解决方案
让解决方案更有价值,做一个有灵魂的开发者
熟练掌握redis,充分利用它的特性和优势
更多Redis相关技术文章,请访问Redis教程栏目进行学习!
以上就是Redis实战之限制操作频率的详细内容,更多请关注其它相关文章!
# 相关内容
# 网站规划与建设实验心得
# 推广网站的创意怎么弄
# 南京品牌网站优化哪家好
# 江门网站内容建设
# 廊坊户型优化分享网站
# 沧州手机网站建设价格
# 综合网站推广有用吗
# 县政府网站建设
# 营销推广的目的是什么
# phpcms 栏目seo标题
# Redis
# 今日
# 自己的
# 如何实现
# 网络带宽
# 能再
# 封印
# 更有
# 博文
# 上传
# 限制操作频率
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
《爱南宁》认证电动车方法
qq邮箱怎么注册_QQ邮箱注册步骤与注意事项
传统曲艺莲花落的表演形式是
如何发挥新媒体矩阵作用?新媒体矩阵怎么搭建?
CodeIgniter 3 中基于 MySQL 数据高效生成动态图表教程
Selenium自动化:利用键盘模拟解决复杂日期输入框输入问题
QQ网页版入口导航 QQ网页版在线访问通道
解决异步Python机器人中同步操作的阻塞问题
小米手机截图后如何查看历史_小米手机截图历史记录查看方法
如何用mysql实现客户反馈管理_mysql客户反馈数据库方法
在Flask应用中安全高效地更新SQLAlchemy用户数据
126邮箱网页在线登录2025_126邮箱网页版入口官方地址
如何测试您的网站全球打开速度-网站海外测速工
oppo手机如何通过下拉通知栏截图_oppo手机通知栏快捷截图方法
苹果电脑如何快速截图并编辑 苹果电脑截屏标注快捷操作
192.168.1.1路由器后台入口 192.168.1.1默认登录入口
VS Code如何设置默认配置
sublime如何自定义文件类型图标_AFileIcon插件的主题切换与个性化配置
使用 .htaccess 正确配置 WordPress 子目录重定向与路径保留
Win10运行窗口在哪里打开 Win10调出运行命令框快捷键【技巧】
PointNet++语义分割模型中类别变更引发的断言错误及标签处理策略
POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩
微星主板BIOS怎么调整内存时序_内存参数手动优化BIOS设置教程
VB表达式书写规则解析
顺丰官方查单号入口 顺丰快递单号查询官网入口
《雷电模拟器》自动点击设置方法
苹果11如何更换iCloud账号_苹果11账号切换的具体步骤
realme 10 Pro息屏方案_realme 10 Pro省电策略
b站怎么用微信登录_b站微信登录方法
word页码灰色不能用如何解决
汽水音乐车机版 汽水音乐车机版官方入口
高效调试PHP大型嵌套数组:JSON序列化与可视化工具实践
谷歌浏览器官方镜像获取方法_谷歌浏览器网页版入口极速直达
秋风萧瑟洪波涌起中的萧瑟指的是什么
百度输入法在AutoCAD中无法输入中文怎么办_百度输入法CAD输入异常解决方法
我的世界官方网址入口 我的世界游戏主页直达入口
批改网网页版登录 批改网电脑版学生登录入口
J*aScript二进制处理_ArrayBuffer与Blob
Go Template中优雅处理循环最后一项:自定义函数实践
微信步数怎么刷_微信步数快速提升技巧
智慧团建活动报名入口 智慧团建活动报名入口手机端官网
知乎APP怎么查看自己被邀请的问题_知乎APP邀请回答记录查看与参与方法
悟空浏览器如何恢复关闭的标签页 悟空浏览器撤销关闭网页快捷键设置
Animex动漫社正版在线入口 Animex动漫社动漫官方观看网
123平台官方登录入口 123邮箱网页端在线沟通工具
谷歌邮箱官方入口链接 谷歌邮箱网页版电脑端快速登录
Python项目中的条件导入:解决跨模块依赖问题
铁路12306怎么申请退票_铁路12306退票申请操作流程
C#中的Record类型有什么优势?C# 9新特性Record与Class的用法区别
猫眼电影app怎么查询电影院的营业时间_猫眼电影影院营业时间查询教程
2019-06-26
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。