项目背景:
之前在做项目的时候,由于是采用微服务架构,所有服务通信使用 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=