实习手册七(Python基于Tornado框架的接口响应服务)使用Redis来缓存数据

目录

前言

Redis

Redis简介

Python操作redis

结语


前言

手册目录:

软件下载及环境安装:

实习手册一(基于Tornado框架的接口响应服务)软件下载与环境配置

Tornado基本框架搭建:

实习手册二(基于Tornado框架的接口响应服务)Tornado基本框架的搭建

Tornado框架中日志的记录,路由的分发,接口的响应:

实习手册三(基于Tornado框架的接口响应服务)Tornado框架中日志的记录,路由的分发,接口的响应

通过PyMySQL,SQLAlchemy在PyCharm中实现对数据的增删改查:

实习手册四(基于Tornado框架的接口响应服务)通过PyMySQL,SQLAlchemy在PyCharm中实现对数据的增删改查

SqlAlchemy的再封装,PyMySQL和SqlAlchemy的结合使用:

实习手册五(基于Tornado框架的接口响应服务)SqlAlchemy的再封装,PyMySQL和SqlAlchemy的结合使用

在Tornado实现对数据库的操作功能:

实习手册六(基于Tornado框架的接口响应服务)在Tornado实现对数据库的操作功能

不知不觉已经到实习手册七了,本章我们要实现利用redis来对数据进行缓存。

Redis

Redis简介

简而言之,redis也跟我们的mysql一样,是一种数据库,跟mysql不同的是,redis是一款高性能的NOSQL系列的非关系型数据库,它是利用内存来存储数据的,而mysql是利用磁盘来存储数据的,这样的特性使得我们利用redis进行数据查询时,速度会比利用mysql要快得多。

Redis的下载及安装已在实习手册一中介绍过,这里不再赘述。

Python操作redis

没有学习过redis的同学可以点击下方这个链接系统化地学习一下:

python操作redis详细教程

使用redis后,我们的数据库查询步骤应该变成这样:

获取到查询请求→将请求传递的参数转化为key→将key传入到查询接口→查询接口调用query方法→先去redis中进行查询,看是否有数据,有则返回,无则去mysql中进行查询,还没有就返回无结果

因此,我们先确定key的格式,key应该是由select语句中的主要参数构成:查什么+去哪查+筛选条件

这里我们以查询用户id,用户名,创建时间为例来进行演示:

    # User表数据模型
    class User(SqlAchBase().base, MysqlBase):
        __tablename__ = 'user'
        userid = Column(Integer, autoincrement=True, primary_key=True)
        uname = Column(String(30))
        pwd = Column(String(30))
        create_time = Column(String(30))
    
    def search_user(self):
        # 获取表名(去哪查)
        table_name = User.__tablename__
        
        # 获取请求参数
        uname = self.get_argument('uname')
        userid = self.get_argument('userid')
        
        # key建立:查询内容+查询表
        key = 'uname,userid,create_time' + '|' + table_name
        
        # 判断筛选条件是否存在,存在的话就拼接到key中
        if uname:
            key += '|' + 'uname="{}"'.format(uname)
        
        if userid:
            key += '|' + 'userid={}'.format(userid)
        
        # 获取查询结果
        result = User.query(key, *[User.userid, User.uname, User.create_time])
        
        # 将结果呈现出来
        self.write(str(result))

因为查询一般调用的是get请求,所以获取参数的方式变成了self.get_argument('参数名称')

然后是MysqlBase中的query方法更改:

@classmethod
    def query(cls, key, *columns):
        cls.TestConn()
        search_list = key.split('|')
        
        # 判断是否获取的到这个key
        if RedisBase.get(key):
            print('successfully get data from redis')
            return RedisBase.get(key)
        else:
            item_list = cls.session.query(*columns or cls).filter(text(search_list[2]+' and '+search_list[3])).all()
            print(item_list)
            RedisBase.set(key, str(item_list), expire_time=10)
            return item_list

然后是RedisBase:

import redis
from settings.config import redis_host, redis_port

class RedisBase():
    redis_tool = None
    @classmethod
    def TestConn(cls):
        if cls.redis_tool:
            print("already connect to redis_tool\n")
            pass
        else:
            pool = redis.ConnectionPool(host=redis_host, port=redis_port, db=0, decode_responses=True)
            cls.redis_tool = redis.Redis(connection_pool=pool)
            print("trying to connect to redis_tool\n")
    @classmethod
    def get(cls, key):
        cls.TestConn()
        return cls.redis_tool.get(key)

    @classmethod
    def set(cls, key, target, expire_time):
        cls.TestConn()
        cls.redis_tool.set(key, target, ex=expire_time)

    @classmethod
    def expire_seconds(cls, key):
        cls.TestConn()
        # 查询某个键的剩余时间
        return cls.redis_tool.ttl(key)

    @classmethod
    def keys(cls):
        cls.TestConn()
        return cls.redis_tool.keys()

    @classmethod
    def delete(cls, key):
        cls.TestConn()
        cls.redis_tool.delete(key)

    @classmethod
    def exists(cls, key):
        cls.TestConn()
        return cls.redis_tool.exists(key)

然后开启redis服务,在访达中前往/usr/local/bin中打开redis-cli和redis-server两个文件,启动redis服务: 

然后在Postman中输入对应的参数,点击Send:

可以看到,我们已经成功查询到了对应的数据。

完整的代码如下:

import redis
from tornado.web import RequestHandler
from tornado.web import Application
from tornado.ioloop import IOLoop
import pymysql
from sqlalchemy import create_engine, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import MetaData
from sqlalchemy import Column, String, Integer

# Redis部分
class RedisBase():
    redis_tool = None
    redis_host = '127.0.0.1'
    redis_port = 6379

    @classmethod
    def TestConn(cls):
        if cls.redis_tool:
            print("already connect to redis_tool\n")
            pass
        else:
            pool = redis.ConnectionPool(host=cls.redis_host, port=cls.redis_port, db=0, decode_responses=True)
            cls.redis_tool = redis.Redis(connection_pool=pool)
            print("trying to connect to redis_tool\n")

    # 获取键
    @classmethod
    def get(cls, key):
        cls.TestConn()
        return cls.redis_tool.get(key)

    # 添加键
    @classmethod
    def set(cls, key, target, expire_time):
        cls.TestConn()
        cls.redis_tool.set(key, target, ex=expire_time)

    # 查询键剩余时间
    @classmethod
    def expire_seconds(cls, key):
        cls.TestConn()
        # 查询某个键的剩余时间
        return cls.redis_tool.ttl(key)

    # 返回全部键
    @classmethod
    def keys(cls):
        cls.TestConn()
        return cls.redis_tool.keys()

    # 删除键
    @classmethod
    def delete(cls, key):
        cls.TestConn()
        cls.redis_tool.delete(key)

    # 判断键是否存在
    @classmethod
    def exists(cls, key):
        cls.TestConn()
        return cls.redis_tool.exists(key)

# SqlAch部分
# URL用来作为SqlAlchemy创造引擎的url
# 格式为:"mysql+pymysql://root:你的mysql密码@localhost:3306/数据库名字"
URL = "mysql+pymysql://root:你的密码@localhost:3306/数据库名字"
class SqlAchBase():
    engine = create_engine(URL)
    base = declarative_base()
    session = sessionmaker(bind=engine)()
    metadata = MetaData()

    @classmethod
    def get_session(cls):
        return cls.session

# Mysql部分
class MysqlBase():
    session = SqlAchBase.get_session()
    conn = None

    # 测试连接方法
    @classmethod
    def TestConn(cls):
        if not cls.conn:
            cls.conn = pymysql.connect(user='root', host='localhost', password=你的密码, db=数据库名称, port=3306)
            print("trying to connect to '%s'" % cls.conn)

        else:
            print("already connected to '%s'" % cls.conn)

    # 增
    @classmethod
    def add(cls, user):
        cls.TestConn()
        cls.session.add(user)
        cls.session.commit()

    # 删
    @classmethod
    def delete(cls, filter):
        cls.TestConn()
        cls.session.query(cls).filter(text(filter)).delete(synchronize_session=False)
        cls.session.commit()

    # 改
    @classmethod
    def update(cls, filter, value):
        cls.TestConn()
        cls.session.query(cls).filter(text(filter)).update(value, synchronize_session=False)
        cls.session.commit()

    # 查
    @classmethod
    def query(cls, key, *columns):
        cls.TestConn()
        search_list = key.split("|")
        if RedisBase.get(key):
            print('successfully get data from redis')
            return RedisBase.get(key)
        else:
            item_list = cls.session.query(*columns or cls).filter(text(search_list[2] + ' and ' + search_list[3])).all()
            print(item_list)
            RedisBase.set(key, str(item_list), expire_time=10)
            return item_list

# User数据模型
class User(SqlAchBase().base, MysqlBase):
    __tablename__ = 'user'
    userid = Column(Integer, autoincrement=True, primary_key=True)
    uname = Column(String(30))
    pwd = Column(String(30))
    create_time = Column(String(30))

# Tornado框架
class SearchHandler(RequestHandler):
    # get请求分发
    def get(self, *args, **kwargs):
        path = self.request.path.split('/')
        method = path[-1]
        if callable(getattr(self, method)):
            getattr(self, method)()
        else:
            self.write("404 not found")

    # search_user接口
    def search_user(self):
        table_name = User.__tablename__
        uname = self.get_argument('uname')
        userid = self.get_argument('userid')
        key = 'uname,userid,create_time' + '|' + table_name
        if uname:
            key += '|' + 'uname="{}"'.format(uname)
        if userid:
            key += '|' + 'userid={}'.format(userid)
        print(key)
        result = User.query(key, *[User.userid, User.uname, User.create_time])

        self.write(str(result))

app = Application([
    (r'/user/search/.*', SearchHandler)
])

if __name__ == '__main__':
    app.listen(8000)
    IOLoop.current().start()

当然,你也可以自己设定redis中键存在的时间,根据需求进行更改就行。

结语

至此,所有的分区板块都已经讲完,接下来将会进入整体项目,会有规范的项目目录,终于不需要将所有代码打在一个程序里了:)。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值