复述中如何限制操作频率

  介绍

这篇文章主要介绍复述中如何限制操作频率,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

<>强场景

<>强场景1

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

<>强场景2

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

<>强场景3

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

<强>抽离本质

在业务开发的过程中,我们不断的参与各种业务场景的方案设计,往往很容易碰到很类似的场景,只不过当前所属的业务模块不一样,其实这些需求的本质是解决同一个问题,当遇到这种场景的时候,我们需要根据自己经验分析抽离出需求的本质问题,实现一个通用的解决方案,让自己的解决方案更有价值,这可能就是区别于你是有灵魂的工程师还是cp(复制粘贴)最强王者吧。

分析上面3个业务场景,可以从中发现其中有相似的逻辑,称它为同类的问题,现在我们就是要抽离这个问题,设计一个通用的解决方案,勾画相同逻辑流程图:

复述中如何限制操作频率

通过分析上面的需求场景,抽离出他们都需要的那些条件:

<李>

限制对象:用户

<李>

限制操作(评论,点赞,记录,…)

<李>

时间范围X秒内

<李>

限制操作数Y次

<李>

超出后禁止操作时间Z(秒/具体时间)

<李>

超出后不让再操作,并提示

复述中如何限制操作频率

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

如果把功能抽离成一个通用函数是不是大概是这样:

& lt; php ?/* *   ,*频率限制   ,* @param  string  action 美元;操作动作   ,* @param  int  userId 美元;发起操作的用户ID   ,* @param  int  time 美元;时间范围X秒内   ,* @param  int  number 美元;限制操作数Y次   ,* @param  array  expire 美元;超出封印时间Z [& # 39;类型# 39;=祝辞1 & # 39;ttl # 39;=祝辞过期时间/秒],[& # 39;类型# 39;=祝辞;2,& # 39;ttl # 39;=祝辞;具体过期时间戳),二选一   ,* @return 保龄球   ,* @throws  \例外   ,*/public  static  function  frequencyLimit (string 行动,美元,int  $ userId, int 时间,美元,int 数美元,美元expire =, [])   {//才能,todo 根据用户操作动作时间范围,进行频率的控制和失效释放   }

<>强解决方案落地

功能中需要对用户发起的操作和时间,以及累计次数进行存储,并且需要失效过期的清理,如果这个时候我们依赖mysql做存储,想想都觉的挺痛苦,这里主角:复述,终于登场了,基于复述,特性,增加的原子操作和关键支持过期机制,内存存储的效率优势,可以相对简单灵活并且又高效的完成目的。

这里简单实现个通用功能的代码:

& lt; php ?/* *   ,*频率限制   ,* @param  string  action 美元;操作动作   ,* @param  int  userId 美元;发起操作的用户ID   ,* @param  int  time 美元;时间范围X秒内   ,* @param  int  number 美元;限制操作数Y次   ,* @param  array  expire 美元;超出封印时间Z [& # 39;类型# 39;=祝辞1 & # 39;ttl # 39;=祝辞过期时间/秒],[& # 39;类型# 39;=祝辞;2,& # 39;ttl # 39;=祝辞;具体过期时间戳),二选一   ,* @return 保龄球   ,* @throws  \例外   ,*/public  function  frequencyLimit (string 行动,美元,int  $ userId, int 时间,美元,int 数美元,美元expire =, [])   {   if 才能;(空(动作)美元,| |,userId 美元;& lt;=, 0, | |, time 美元;& lt;=, 0, | |, number 美元;& lt;=, 0), {   ,,,throw  new  \异常(& # 39;非法参数& # 39;);   ,,}   时间=美元才能key  & # 39;行为:限制:& # 39;,只action 美元;只& # 39;:& # 39;,只userId美元;   时间=美元才能r  RedisClient: connect ();//才能获取当前累计次数   时间=美元才能current  intval中($ r→(键)美元);   if 才能;(current 美元;祝辞=,美元数),return 假;//累才能计并返回最新值   时间=美元才能current  $ r→增加(关键);//第才能一次累加,设置控制操作频率的有效时间   if 才能;(current 美元;===,1),$ r→到期(关键美元,,时间);//未才能超出限制次数先放过   if 才能;(current 美元;& lt;,美元数),return 真实;//超才能出后根据需要重新设置过期失效时间,current 美元;===,number 美元;判断保证只重新设置一次=美元才能type 空(到期美元[& # 39;类型# 39;]),?,0,:,intval中(到期美元[& # 39;类型# 39;]);=美元才能ttl 空(到期美元[& # 39;ttl # 39;]), ?, 0,:, intval中(到期美元[& # 39;ttl # 39;]);   if 才能;(current 美元;===,number 美元;,,,ttl 美元;祝辞,0,,,,in_array(类型、美元,[1,2])),{   ,,,if  (type 美元;===,1),$ r→到期(关键美元,,ttl);   ,,,if  (type 美元;===,2),$ r→expireAt(关键美元,,ttl);   ,,}   return 才能;假;   }//场景1/* *   ,*评论限制   美元,* @param  int  userId   ,* @return  bool |字符串   ,*/public  function  doComment (int  userId美元)   {   try {才能   ,,,pass 美元;=,FrequencyLimit: doHandle(& # 39;评论# 39;,,userId美元,30岁,10);   ,,,if (! $通过),return  & # 39;过于频繁& # 39;;   ,,,//,todo 评论逻辑   ,,,return 真实;   ,,},catch  (\ Exception  $ e), {   ,,,return  e→美元getMessage ();   ,,}   }//场景2/* *   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null

复述中如何限制操作频率