接口视图代码实现:发送短信验证码可以使用容联云通讯实现
# 生成短信验证码
class SMSCodeView(View):
def get(self, request, mobile):
# 注意:image_code_id就是uuid
image_code = request.GET.get('image_code')
uuid = request.GET.get('image_code_id')
if not all([image_code, uuid]):
return JsonResponse({'code': 400, 'errmsg': '缺失必传参数'})
# 读取redis中的图片验证码
conn = get_redis_connection('verify_code')
image_code_from_redis = conn.get('img_%s' % uuid)
if not image_code_from_redis:
return JsonResponse({'code': 400, 'errmsg': '图片验证码失效,不存在'})
if image_code.lower() != image_code_from_redis.decode().lower():
return JsonResponse({'code': 400, 'errmsg': '验证码输入错误!!!'})
# 为了防止图形验证码被频繁验证,原则上一个图形验证码只能使用一次
# 解决方案:从redis中读取,就直接销毁
conn.delete('img_%s' % uuid)
# 2.1 生成一个随机的短信验证码(6位数)
sms_code = "%06d" % random.randint(0, 999999)
print('手机短信验证码:', sms_code)
flag = conn.get('sms_flag_%s' % mobile)
if flag:
return JsonResponse({'code': 400, 'errmsg': '请勿重复发送短信'})
p = conn.pipeline() # 获取一个管道对象
try:
p.setex('sms_%s' % mobile, 300, sms_code)
# 添加标志位
p.setex('sms_flag_%s' % mobile, 60, '-1')
p.execute() # 通过管道批量执行redis命令
except Exception as e:
return JsonResponse({
'code': 400,
'errmsg': 'redis数据库访问失败'
})
# TODO:
# 2.3 调用云通讯发送短信
# 2.3 发布"发送短信"任务,交给异步程序去执行,此处不会阻塞
return JsonResponse({
'code': 0,
'errmsg': 'OK'
})
优化1:避免一分钟内重复发送短信
优化2:pipeline 操作 Redis 数据库
-问题引入:
如果Redis服务端需要同时处理多个请求,加上网络延迟,那么服务端利用率不高,效率降低。
- 解决的办法:
管道 pipeline
往常的不加管道的实现过程:
实现原理:
实现的原理是队列。
Client 可以将三个命令放到一个 tcp 报文一起发送。
Server 则可以将三条命令的处理结果放到一个 tcp 报文返回。
队列是先进先出,这样就保证数据的顺序性。
实现:
# 创建 Redis 管道
pl = redis_conn.pipeline()
# 将 Redis 请求添加到队列
pl.setex('sms_%s' % mobile, 300, sms_code)
pl.setex('send_flag_%s' % mobile, 60, 1)
# 执行请求, 这一步千万别忘了
pl.execute()