redis学习(一)

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 和数据库中同时删除。