天天看点

短信验证码后端-接口设计

短信验证码后端-接口设计
短信验证码后端-接口设计
短信验证码后端-接口设计

接口视图代码实现:发送短信验证码可以使用容联云通讯实现

# 生成短信验证码
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()