redis 学习(一)
redis 是一种应用广泛的nosql数据库,和mysql相比,在内存中的nosql读写速度极快,能在很多场景发挥自己的用处
1 安装
ubuntu 下直接是用
sudo apt install redis-server
就可以在服务器安装好一个redis,同时redis-cli 也可以通过终端使用
redis-cli
输入
ping
回复PONG
表示正常。这个时候基本的安装可以说结束,但还是要做一定的配置
使用 sudo vim /etc/redis/redis.conf
修改配置文件,
注释掉bind 127.0.0.1
,这一句限制了redis只能本地连接,
添加bind 0.0.0.0
使得所有的ip 都能链接到redis ,如果你是通过固定的ip 进行链接,也可以改成特定,同时服务器添加安全组,开放 6379 端口
另外需要添加一句设定
127.0.0.1:6379> config set stop-writes-on-bgsave-error no
可以解决因强制关闭导致redis快照不能持久化的问题,但如果你不会随便的关机的话最好还是不要用上
做完这三步基本完成了单机redis的安装。可以通过各种的方式来使用redis。
2redis 作为登陆缓存
在登陆技术中,session是很重要的一环,使用redis可以很方便的实现session,在这个过程中主要用到redis的hash数据结构,我采用python作为实现语言,tornado作为web框架,python redis是相关的驱动,在接下来实现了一个登陆session
class LoginHandler(web.RequestHandler):
md5 = hashlib.md5()
session = Session()
def get(self):
self.render('login.html')
def query_user(self, email):
return self.session.query(User).filter_by(email=email).first()
# 在redis 中查找令牌,返回一个包含user infomation的dict
def check_token(self,token):
user = conn.hget('login', token)
if user is not None:
return json.loads(user)
return None
# user 是一个包含了user information的dict
# user = {'id':user.id,'name':user.name,'login_time':datetime.timestamp}
def set_token(self, token, user):
user['login_time'] = datetime.timestamp(datetime.now())
user = json.dumps(user)
return conn.hset('login', token, user)
# user 是一个包含了user info的dict
def update_token(self, token, user):
user['login_time'] = datetime.timestamp(datetime.now())
user = json.dumps(user)
return conn.hset('login',token,user)
def make_token(self, user):
return {'id':user.id,
'login_name':user.name }
def make_cookie(self,email):
self.md5.update(email.encode('utf-8'))
return self.md5.hexdigest()
def post(self):
email = self.get_argument('email')
login_name = self.get_argument('login_name')
password = self.get_argument('password')
if login_name is None or password is None or email is None:
self.set_status(403)
self.write({'message':'data missing'})
self.md5.update(password.encode('utf-8'))
hash_passwd = self.md5.hexdigest()
# 先从缓存中寻找,如果不存在在从数据库中查找
login_user = self.check_token(email)
if login_user is not None:
self.update_token(email,login_user)
self.set_status(403)
self.write({'message':'had login'})
return
login_user = self.query_user(email)
print(login_user)
if login_user is None:
self.set_status(404)
self.write({'message':'no user'})
return
elif login_user.hashed_passwd == hash_passwd:
self.set_cookie('email',self.make_cookie(email))
self.set_token(login_user.email,self.make_token(login_user))
return self.write({'message':'login successful'})
return self.write({'message':'password wrong'})
思路既是在登陆请求到来时先从redis 查询是否有相关的token, 登陆的session 存放在一个名为login
的hash结构中。
在设定上email 对于每一个用户都是唯一的,所以可以用作hash的token,如果在token 里就更新token,如果不在则在数据库中查询,查询到之后将用户信息放回redis 用作下次登陆用,如果存在删除用户的需求,则需要在redis 和数据库中同时删除。