php redis 短信频率,发送短信: 使用Redis限制每天的发送频率和发送时间

ad0b0a01b934d97428d7dab72a82a33d.png

ratelimiting.lua

--[[实现访问频率的脚本.参数:KEY[1] 用来标识同一个用户的idARGV[1] 过期时间ARGV[2] 过期时间内可以访问的次数返回值: 如果没有超过指定的频率, 则返回1; 否则返回0]]local times = .call('incr', KEYS[1])if times == 1 then-- 说明刚创建, 设置生存时间redis.call('expire', KEYS[1], ARGV[1])endif times > tonumber(ARGV[2]) thenreturn 0endreturn 1

56828.png

该脚本也更加直观:

Redis网站上有很多Redis. 这里我们使用Jedis.

让我们看一下代码. 该程序中的ClassPathResource和FileCopyUtils类是Spring中的类,因此此处的示例程序取决于Spring

d9df1857db897acdd35d3b47de361967.png

RateLimit.java

public class RateLimit {private JedisPool jedisPool;private String script;// 省略了构造方法public void init() throws Exception {ClassPathResource resource = new ClassPathResource("script/ratelimiting.lua");script = FileCopyUtils.copyToString(new EncodedResource(resource, "UTF-8").getReader());}/*** 提供限制速率的功能** @param key 关键字* @param expireTime 过期时间* @param count 在过期时间内可以访问的次数* @return 没有超过指定次数则返回true, 否则返回false*/public boolean isExceedRate(String key, long expireTime, int count) {List params = new ArrayList<>();params.add(Long.toString(expireTime));params.add(Integer.toString(count));try(Jedis jedis = jedisPool.getResource()) {List keys = new ArrayList<>(1);keys.add(key);Long canSend = (Long) jedis.eval(script, keys, params);return canSend == 0;}}}

b61c42485d87c875b586a3da762e4b7d.png

此处init方法的作用是读取我们刚刚写入脚本变量中的脚本以供以后使用.

isExceedRate方法将关键字和参数(到期时间和传输次数)封装到List中,然后使用Jedis调用脚本. 获取返回值并确定频率是否太高.

下面,我们使用上述代码完成限制发送频率的功能(有关某些接口和类的声明,请参阅“发送SMS限制发送频率”). 限制每日传输次数的代码基本相同短信网页版,因此我不会在此处发布,请下载源代码以查看.

cd021309c922c8e612160358f5d481e7.png

FrequencyFilter

public class FrequencyFilter implements SmsFilter {private static final String KEY_PREFIX = "rate.frequency.limiting:";private RateLimit rateLimit;private int sendInterval;// 省略了部分代码@Overridepublic void filter(Sms sms) throws FrequentlyException {if(rateLimit.isExceedRate(KEY_PREFIX+sms.getMobile(), sendInterval, 1)|| rateLimit.isExceedRate(KEY_PREFIX+sms.getIp(), sendInterval, 1)){throw new FrequentlyException("发送短信过于频繁");}}}

至此,我们的主要代码已完成,可以看到使用Redis之后该代码确实非常简单.

因为我还没有性能测试,所以我只是使用了for循环来测试性能. 尽管它可能不太准确,但也具有一定的置信度. 当限制发送频率时,使用ConcurrentMap的性能会更高. ,该比率似乎不小,但是由于基数不大短信网页版,因此不需要花费很多时间(100,000条记录仅花费了15秒). 但是,当限制发送天数时,还剩下n个以上的时间. 总体而言,仅使用Redis可以节省更多时间和精力. 此外,个人猜测,当扩展到集群时,应该更容易使用Redis.

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/tongxinshuyu/article-254787-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值