python3 Flask Redis 如何切换数据库

本文介绍了在Python Flask项目中使用Redis时如何动态切换数据库。由于redis-py为保证线程安全未实现SELECT指令,flask_redis也不支持,因此提出了通过每次重新连接并指定数据库的解决方案。代码示例展示了如何封装一个支持动态切换数据库的Redis类,并给出了使用Flask配置文件的方法。文章还提到为了适应ORM对象,push_redis进行了相应调整,并强调了关闭数据库的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目背景:
之前在做项目的时候,由于是采用微服务架构,所有服务通信使用 Redis 作为数据交互层。需求是不同类型的数据存储在不同的数据库中,不同的数据库就需要动态切换 Redis 数据库。

Redis 默认有 16 个数据库,index(值范围:0~15),默认 index=0。切换数据库命令为:select index

但是呢,flask_redis 却没有这个功能。为什么会没有呢?因为 redis-py 就没有。flask_redis 是基于 redis-py 进行二次封装的库,redis-py 为了保证 Redis 实例的线程安全,没有实现 SELECT 指令。如果有不明白的欢迎扣扣裙询问哦(++六零六九一六八三一)

Redis
客户端实例可以安全地在线程间共享。从内部实现来说,只有在命令执行时才获取连接实例,完成后直接返回连接池,命令永不修改客户端实例的状态。但是,有一点需要注意:SELECT
命令。SELECT
命令允许切换当前连接使用的数据库。新的数据库保持被选中状态,直到选中另一个数据库或连接关闭。这会导致在返回连接池时,连接可能指定了别的数据库。因此,redis-py
没有在客户端实例中实现 SELECT 命令。如果要在同一个应用中使用多个 Redis
数据库,应该给第一个数据库创建独立的客户端实例(可能也需要独立的连接池)。

解决方案

flask_redis 既然不能动态切换数据库,那我们就从根源入手——使用前都重新连接并指定数据库。

感觉是挺暴力的,其实,这是官方建议的做法。自己动手丰衣足食,接下来我们就来封装一个支持动态切换数据库的 Redis,需要满足用户在使用的时候无感知。

废话不多说,直接上代码:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import copy
import datetime

from redis import StrictRedis, ConnectionPool


class RedisLib(object):

    def __init__(self, redis_db, redis_url, blacklist=None):
        self.redis = None
        self.redis_db = redis_db
        self.redis_url = redis_url
        self.blacklist = blacklist
        self.blacklist_data = None

    def select(self, db):
        url = '%s/%s' % (self.redis_url, db.split('db')[1])
        pool = ConnectionPool.from_url(url=url, decode_responses=True)
        self.redis = StrictRedis(connection_pool=pool)

    def push_redis(self, db, data):

        def handle_data():

            self.blacklist_data = [value for value in map(
                lambda index: data.pop(index) if data.get(index) else None, self.blacklist)]

            key = '%s:%s' % (self.redis_db[db], data['id'])

            for k, v in data.items():
                self.redis.hset(key, k, v.strftime("%Y-%m-%d %H:%M:%S") if isinstance(
                    v, datetime.datetime) else (v if v else ''))

        self.select(db)

        if isinstance(data, list):
            for obj in data:
                data = copy.deepcopy(obj.__dict__)
                handle_data()
        else:
            data = copy.deepcopy(data.__dict__)
            handle_data()

    def pull_redis(self, db, _id=None):

        self.select(db)

        key = '%s:%s' % (self.redis_db[db], _id if _id else '')

        if _id is None:
            data = self.redis.dbsize()
        elif _id == 'key':
            data = self.redis.keys()
        elif _id == '*':
            data = [self.redis.hgetall(key) for key in self.redis.keys()]
        else:
            data = self.redis.hgetall(key)
        return data

    def __del__(self):
      self.redis.connection_pool.disconnect()

以上代码就是实现了新增数据、获取数据、切换数据库的功能,在实例化的时候需要进行配置。虽然可以使用了,但是并不友好,因为我每次都得需要指定数据库,那有没有什么方法可以连数据库指定都不用呢?

当然有的啦!

那就是再写一个[狗头]哈哈!

class HandleQueue(RedisLib):

    def __init__(self):

        self.redis_db = {
            'db0': None,
            'db1': 'oss:aop:user',
            'db9': 'oss:aop:role'
        }

        self.redis_url = 'redis://127.0.0.1:6379'

        # Flask app config from redis url
        # from app import app
        # self.redis_url = app.config['REDIS_URL']

        self.blacklist = ['_sa_instance_state', 'version', 'status']

        RedisLib.__init__(self, self.redis_db, self.redis_url, self.blacklist)

    def set_user_data(self, data):
        return self.push_redis('db1', data)

    def get_user_data(self, user_id=None):
        return self.pull_redis('db1', user_id)

    def set_role_data(self, data):
        return self.push_redis('db9', data)

    def get_role_data(self, dict_id=None):
        return self.pull_redis('db9', dict_id)


if __name__ == '__main__':
    handle_queue = HandleQueue()
    return_value = handle_queue.get_user_data(1)
    print(return_value)

运行结果:

{'username': '极客点儿', 'role_id': '2', 'phone': '', 'account': 'GeekDot', 'mail': '', 'update_time': '2020-09-22 15:52:32', 'create_time': '2020-08-13 16:51:51', 'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDA4NDc1NTIsImlhdCI6MTYwMDc2MTE1MiwiaXNzIjoiMjF2aWFuZXQiLCJkYXRhIjp7ImlkIjoxfX0.fEAfuRC3tvA-qv5j6Xjbqu9W8ksY4PZwYwFoI3ST3xU', 'number': '', 'id': '1'}

通过类继承把切换数据库等基本功都保留,然后通过构造函数配置数据库,最后用到哪些数据和数据库就写一个很简单的方法即可。

因为我们是 Flask 项目,所以要使用 Flask 的配置文件,方法如下,也很简单。

# Flask app config from redis url
# from app import app
# self.redis_url = app.config['REDIS_URL']

因为项目组中用的是 ORM 所以 push_redis 现在只能接受 ORM 对象。如果想支持其他对象,可以自己改写,也简单。

最后别忘了使用析构函数将数据库关闭!以上为部分代码,需要源码的可以来扣扣裙,群里有免费的源码和python学习资料。
在这里插入图片描述

### 集成 RedisFlask 应用中的方法 要在 Python Flask 应用中使用 Redis 实现缓存功能,可以通过安装 `redis` 和 `Flask-Redis` 库来完成。以下是具体实现的方式: #### 1. 安装必要的库 首先需要安装两个主要的依赖项:`redis` 和 `Flask-Redis`。这可以通过 pip 工具轻松完成[^1]。 ```bash pip install redis flask-redis ``` #### 2. 初始化 Redis 连接 通过导入 `redis` 模块并创建一个连接对象,可以初始化与 Redis 数据库之间的通信通道[^2]。 ```python import redis # 创建 Redis 连接池 redis_pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=1) # 获取 Redis 连接实例 redis_db = redis.Redis(connection_pool=redis_pool) ``` #### 3. 缓存装饰器的定义 为了方便在视图函数中使用 Redis 缓存,可以自定义一个基于 Redis 的缓存装饰器。该装饰器会自动处理请求的结果存储和读取逻辑。 ```python from functools import wraps from flask import request def cache_result(timeout=300): # 默认超时时间为 5 分钟 def decorator(func): @wraps(func) def wrapper(*args, **kwargs): key_prefix = f"{request.path}:{func.__name__}" result_key = f"cache:{key_prefix}" # 尝试从 Redis 中获取缓存的数据 cached_data = redis_db.get(result_key) if cached_data is not None: return cached_data.decode('utf-8') # 如果没有找到缓存,则调用原始函数计算结果 result = func(*args, **kwargs) # 存储到 Redis 并设置过期时间 redis_db.setex(result_key, timeout, result) return result return wrapper return decorator ``` #### 4. 使用缓存装饰器优化性能 将上述装饰器应用于任何希望加速响应速度的视图函数上即可。这样每次访问相同路径时都会优先尝试加载已有的缓存数据而不是重新执行业务逻辑。 ```python from flask import Flask app = Flask(__name__) @app.route('/example') @cache_result(timeout=60) # 设置此路由的缓存有效期为 60 秒 def example(): return "这是一个被缓存的例子" ``` #### 5. 配置高级选项 (可选) 对于更复杂的项目需求来说,还可以利用额外的一些配置参数来自定义行为模式,比如调整默认超时时长或者更改密钥前缀等等[^3]。 ```python class Config(object): CACHE_TYPE = 'redis' CACHE_REDIS_HOST = '127.0.0.1' CACHE_REDIS_PORT = 6379 CACHE_REDIS_DB = 0 CACHE_DEFAULT_TIMEOUT = 300 app.config.from_object(Config) ``` --- ### 总结 以上就是在 Python Flask 应用程序里集成 Redis 来充当缓存层的主要流程说明。通过这种方式不仅可以显著提升高频次查询接口的服务质量,同时也降低了后端数据库的压力水平^。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值