redis是什么
REmote DIctionary Server(Redis)
是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
详细关于redis的介绍可以去看这里:https://www.runoob.com/redis/redis-tutorial.html
Python使用redis
安装 redis 模块
在python中,如果需要操作redis,那么需要先安装相应的第三方模块,在这里我使用的是python-redis
,可以使用下面的命令进行安装。
pip install python-redis
测试是否安装成功
>>>python
>>>import redis
如果没有报错,则说明redis安装成功。
简单的python操作redis
redis 提供两个类 Redis 和 StrictRedis, StrictRedis 用于实现大部分官方的命令,Redis 是 StrictRedis 的子类,用于向后兼用旧版本。
redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串。
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob') # 设置 name 对应的值
print(r['name'])
print(r.get('name')) # 取出键 name 对应的值
print(type(r.get('name'))) # 查看类型
输入结果:
runoob runoob <class 'str'>
使用redis存储、验证验证码
有了上述的先行知识,我们就可以使用redis存储验证码,进行相关的业务逻辑操作了。用户重置密码的流程如下图所示。
使用redis存储验证码
在用户开始了密码重置操作,我们需要将验证码发送到用户的注册邮箱中,此时,redis也应该保存该验证码,并且设置一个过期时间,操作此段时间后,验证码就失效了。代码如下所示:
# extension.py
import redis
# 使用连接池的方式连接,提高系统性能
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
rd = redis.Redis(connection_pool=pool)
# auth.py
@auth_bp.route('/password-reset/', methods=['GET', 'POST'])
def reset_password():
email = request.form.get('email')
user = User.query.filter_by(email=email).first()
if not user:
flash('邮箱不存在,请输入正确的邮箱!', 'danger')
return redirect(url_for('.forget_pwd'))
ver_code = generate_ver_code()
# 将验证码设置到redis中,过期时间为10分钟
rd.set(user.id, ver_code, ex=current_app.config['EXPIRE_TIME'])
token = generate_token(user=user, operation=Operations.RESET_PASSWORD)
send_reset_password_email(user=user, token=token, ver_code=ver_code)
flash('验证邮件发送成功,请到邮箱查看然后重置密码!', 'success')
return render_template('main/auth/pwdResetNext.html')
使用redis验证验证码
在完成上面的操作之后,用户的邮箱会收到一个邮件,里面包含有重置密码的连接以及验证码。之后我们就可以使用redis来验证验证码了,代码如下。
@auth_bp.route('/reset-confirm/', methods=['POST', 'GET'])
def reset_confirm():
if current_user.is_authenticated:
return redirect(url_for('.login'))
form = ResetPwdForm()
if form.validate_on_submit():
email = form.email.data
usr = User.query.filter_by(email=email).first()
# 如果输入的邮箱不存在
if not usr:
flash('邮箱不存在,请输入正确的邮箱~', 'danger')
return render_template('main/auth/resetPwd.html', form=form)
# 如果验证码已经超出了有效时间
if rd.get(usr.id) is None:
flash('验证码已过期.', 'danger')
return render_template('main/auth/resetPwd.html', form=form)
pwd= form.confirm_pwd.data
ver_code = form.ver_code.data
# 如果输入的验证码与redis中的不一致
if ver_code != rd.get(usr.id):
flash('验证码错误')
return render_template('main/auth/resetPwd.html', form=form)
usr.set_password(pwd)
db.session.commit()
flash('密码重置成功!', 'success')
return redirect(url_for('.login'))
return render_template('main/auth/resetPwd.html', form=form)
在上面的代码中,我们可以通过rd.get(usr.id)
来获取当前用户的验证码,同时如果用户重复操作,验证码会自动替换成最新的验证码,如果验证码过期,那么通过rd.get(usr.id)
的值将会为空。
至此,一个简单的验证码验证就完成了。当然如果真要用在大型项目上,那么不仅仅是这么简单的操作,需要考虑到的东西十分多!!!
同时,redis的功能不仅于此,想想一个场景,在关系数据库中,例如MySQL,如果一张表中的数据变化频率非常的小,同时表中的数据又十分的多了,如果每次访问该表都去进行查询的话,如果数据库优化做的好,那么查询速度还是可观,如果像我这种数据库渣渣的话,那么查询时间肯定又长又臭了。因此我们可以将更新频率不高的数据放入redis缓存中去,毕竟别人是内存性数据库,这数据不是你MySQL能比拟的,但是也需要注意以下几点
- 数据一致性,即缓存数据库中数据应该与MySQL中保持一致,不能出现数据滞后更新等状态
- 不要缓存那些对数据一致性要求很高的数据
上述代码都是个人博客网站的代码片段,如果需要看到效果,可以前往Blogin源代码。
Macv 博主 2020-11-03T18:26:10
写的不错啊 小伙子