暂时不考虑 ip,什么的限制,只考虑 手机号限制,
ip
如何用redis做到限制,一个手机号,1分钟内最多发一条,一天内最多10条
redis
各位大神有什么好方案,先谢!(崇拜脸)
业精于勤,荒于嬉;行成于思,毁于随。
需要两个缓存
key名称 phone-busy,缓存1分钟
key名称 phone-send-count,缓存1天,每成功发送一条+1
发送的时候流程如下:
判断phone-busy是否存在,存在直接报错“发送过快”。
判断phone-send-count是否存在,存在则继续检测是否等于10,存在且等于10报错“您今天不能发送短信了”
发送短信
写入phone-busy,有效期1分钟
写入phone-send-count+1,有效期当天23:59:59的时间戳-当前时间戳
用手机号+分钟,手机号+天做为key分别限制一分钟和一天内发送短信的数量
1分钟内最多发一条,用分钟和手机号为key:min:201701041750:13888888888一天内最多10条,用日期和手机号号为key:day:20170104:13888888888
min:201701041750:13888888888
day:20170104:13888888888
//php demo function check($phone){ if($redis->exists('min:'.date('YmdHi').':'.$phone) || $redis->get('day:'.date('YmdHi').':'.$phone) > 10){ reutrn false; } $redis->set('min:'.date('YmdHi').':'.$phone,1); $redis->incr('day:'.date('Ymd').':'.$phone); return true; } // 这样按分钟生成的key比较多,可以把手机号对应的分钟放`set`内
写一段伪代码如下:
String sendFrequencyKeyPrefix = "send_frequency_"; String dailySendLimitKeyPrefix = "daily_send_limit_"; public function sendMessage(String phoneNumber, String message){ if(redis.get((sendFrequencyKeyPrefix + phoneNumber))) { return false; } int dailySendTotal = int(redis.get((dailySendLimitKeyPrefix + phoneNumber))); if(dailySendTotal >= 10) { return false; } // send message here redis.set((sendFrequencyKeyPrefix + $phoneNumber), "", 60); redis.set((dailySendLimitKeyPrefix + $phoneNumber), dailySendTotal + 1, 3600*24); return true; }
大概意思就是这样了,可以将一分钟,一天的发送限制做成配置文件,灵活多变。
1月5日修改;
这里@Lowky 朋友提醒了一个问题,就是每天这个限制,到底是一天还是24小时,因为这两个概念是不一样的。这里楼主要的应该是每天限制10条,每天凌晨限制放开。每分钟应该就不考虑这个了。code修改如下:
String sendFrequencyKeyPrefix = "send_frequency_"; public function sendMessage(String phoneNumber, String message){ String dailySendLimitKeyPrefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); if(redis.get((sendFrequencyKeyPrefix + phoneNumber))) { return false; } int dailySendTotal = int(redis.get((dailySendLimitKeyPrefix + phoneNumber))); if(dailySendTotal >= 10) { return false; } // send message here redis.set((sendFrequencyKeyPrefix + $phoneNumber), "", 60); redis.set((dailySendLimitKeyPrefix + $phoneNumber), dailySendTotal + 1, 3600*24); return true; }
第一个问题,设置过期时间就可以实现了,只要手机号存在于Redis,就是说明没到1分钟第二个问题,每次发送的时候更改一下计数器,将计数器过期时间设为一天
简单说明:
你要有两个key
一个1分钟过期的key
一个24h过期的key
按照短信业务来处理,都是按照有效时长,不按照0点结算。
需要两个缓存
key名称 phone-busy,缓存1分钟
key名称 phone-send-count,缓存1天,每成功发送一条+1
发送的时候流程如下:
判断phone-busy是否存在,存在直接报错“发送过快”。
判断phone-send-count是否存在,存在则继续检测是否等于10,存在且等于10报错“您今天不能发送短信了”
发送短信
写入phone-busy,有效期1分钟
写入phone-send-count+1,有效期当天23:59:59的时间戳-当前时间戳
用手机号+分钟,手机号+天做为key分别限制一分钟和一天内发送短信的数量
1分钟内最多发一条,用分钟和手机号为key:
min:201701041750:13888888888
一天内最多10条,用日期和手机号号为key:
day:20170104:13888888888
写一段伪代码如下:
大概意思就是这样了,可以将一分钟,一天的发送限制做成配置文件,灵活多变。
1月5日修改;
这里@Lowky 朋友提醒了一个问题,就是每天这个限制,到底是一天还是24小时,因为这两个概念是不一样的。这里楼主要的应该是每天限制10条,每天凌晨限制放开。每分钟应该就不考虑这个了。code修改如下:
第一个问题,设置过期时间就可以实现了,只要手机号存在于Redis,就是说明没到1分钟
第二个问题,每次发送的时候更改一下计数器,将计数器过期时间设为一天
简单说明:
你要有两个key
一个1分钟过期的key
一个24h过期的key
按照短信业务来处理,都是按照有效时长,不按照0点结算。