数据库、redis连接池

import contextlib
import redis
import pymysql

IS_DEV = False
if IS_DEV:
    # 正式版redis
    REDIS = {
        'host': '**********.redis.rds.aliyuncs.com',
        'port': 6379,
        'db': 11,
        'password': '********'
    }
    # 正式版数据库
    DB_INFO = {
        'host': '************.mysql.rds.aliyuncs.com',
        'port': 3306,
        'user': 'mysqlsa',
        'password': '********',
        'db': '*****agent'
    }
    ADS_INFO = {
        'host': '************.ads.aliyuncs.com',
        'port': 3306,
        'user': 'agent_sa',
        'password': '********',
        'db': '*****agent'
    }
else:
    # 测试版 线下 redis
    REDIS = {
        'host': '192.168.0.8',
        'port': 6379,
        'db': 10,
        'password': '******'
    }
    # 测试版数据库
    DB_INFO = {
        'host': '***********.mysql.rds.aliyuncs.com',
        'port': 3306,
        'user': 'mysqlsa',
        'password': '*******',
        'db': '******agent'
    }
    ADS_INFO = {
        'host': '***********.ads.aliyuncs.com',
        'port': 3306,
        'user': 'mysqlsa',
        'password': '********',
        'db': '******agent'
    }


# 创建数据库连接池池
class DatabaseConnectPool:
    '''
    数据库连接池类  支持多库多池
    '''

    def __init__(self, module, credentials, size=10):
        '''
        :param module: 数据库驱动 例如 pymysql
        :param credentials: 数据库连接信息
        credentials={
                'DB_INFO' = {
                'host': 'rm-uf6t4r3u8vea8u340971.mysql.rds.aliyuncs.com',
                'port': 3306,
                'user': 'res_sql',
                'password': 'Lansi321',
                'db': 'lansi_agent'
            }
        }
        :param size: 每个连接池最大连接数量
        '''
        self.__module = module
        self.__credentials = credentials
        self.__databases = {}
        self.__size = size

    def get(self, pool_name):
        '''
        根据连接池名称获取连接
        :param pool_name:
        :return:
        '''
        if pool_name not in self.__credentials:
            raise Exception('数据库信息不存在')
        elif pool_name not in self.__databases:
            self.__databases[pool_name] = []
            self.create_connection(pool_name)
        elif not self.__databases[pool_name]:
            self.create_connection(pool_name)
        con = self.__databases[pool_name].pop()
        try:
            con.ping()
        except Exception as e:
            con = e
        return con

    def create_connection(self, pool_name):
        '''
        创建数据库连接
        :param pool_name:
        :return:
        '''
        if pool_name not in self.__credentials:
            raise Exception('数据库信息不存在')
        db_info = self.__credentials[pool_name]
        con = self.__module.connect(**db_info)
        self.__databases[pool_name].append(con)

    def put(self, pool_name, con):
        '''
        把数据库连接放回连接池
        :param pool_name:
        :param con:
        :return:
        '''
        if isinstance(con, self.__module.connections.Connection):
            if len(self.__databases[pool_name]) > self.__size:
                con.close()
            self.__databases[pool_name].insert(0, con)
        else:
            try:
                con.close()
            except:
                pass

    def __del__(self):
        for con_list in self.__databases.values():
            for con in con_list:
                try:
                    con.close()
                except:
                    pass


db_info = {
    # 连接池名称: 数据库信息
    'rds': DB_INFO,
    'ads': ADS_INFO
}
db_pool = DatabaseConnectPool(pymysql, db_info)


def search_sql_pool(total_sql, pool_name='rds', result_type='dict'):
    '''
    多库查询
    :param total_sql: 被执行的sql
    :param pool_name: 连接池名称
    :param db_name: 数据库名
    :param result_type: 返回结果类型  默认字典
    :return:
    '''
    # 从数据库连接池池中获取连接池
    db = db_pool.get(pool_name)
    # 如果没有取出连接  直到取到连接
    while isinstance(db, str):
        db = db_pool.get(pool_name)
    if result_type == 'dict':
        try:
            with db.cursor(pymysql.cursors.DictCursor) as cursor:
                # 使⽤execute⽅法执⾏SQL语句
                cursor.execute(total_sql)
                # 获取数据
                data = cursor.fetchall()
            # 提交
            db.commit()
        except Exception as e:
            data = e
        finally:
            db_pool.put(pool_name, db)
    # 返回列表类型查询结果
    else:
        try:
            with db.cursor() as cursor:
                # 使⽤execute⽅法执⾏SQL语句
                cursor.execute(total_sql)
                # 获取数据
                data = cursor.fetchall()
            # 提交
            db.commit()
        except Exception as e:
            data = e
        finally:
            db_pool.put(pool_name, db)
    return data


def rds_sql(total_sql):
    '''
    RDS查询  返回字典
    :param total_sql:
    :return:
    '''
    return search_sql_pool(total_sql, pool_name='rds')


def rds_list_sql(total_sql):
    '''
    RDS查询  返回列表
    :param total_sql:
    :return:
    '''
    return search_sql_pool(total_sql, pool_name='rds', result_type='list')


def ads_sql(total_sql):
    '''
    ADS查询  返回字典
    :param total_sql:
    :return:
    '''
    return search_sql_pool(total_sql, pool_name='ads')


def ads_list_sql(total_sql):
    '''
    ADS查询  返回列表
    :param total_sql:
    :return:
    '''
    return search_sql_pool(total_sql, pool_name='ads', result_type='list')


# 创建redis连接池
class RedisConnectPool:
    '''
    redis连接池 使用的是对redis模块封装了一层
    '''

    def __init__(self, redis_info, size=10):
        '''
        初始化连接池
        :param redis_info: {
            'host': '192.168.0.8',
            'port': 6379,
            'db': 10,
            'password': 'Lansi.123'
        }
        :param size: 每个连接池最大连接数量
        '''
        self.__redis_info = redis_info
        self.__connections = []
        self.__size = size

    @contextlib.contextmanager
    def get(self):
        '''
        获取一个连接
        :return:
        '''
        if not self.__connections:
            self.create_connection()
        con = self.__connections.pop()
        con.ping()
        yield con
        self.put(con)

    def create_connection(self):
        '''
        创建连接
        :return:
        '''
        con = redis.Redis(decode_responses=True, **self.__redis_info)
        self.__connections.append(con)

    def put(self, con):
        '''
        把连接放回连接池
        :param con:
        :return:
        '''
        if isinstance(con, str):
            return
        if self.__size < len(self.__connections):
            con.close()
        elif isinstance(con, redis.client.Redis):
            self.__connections.insert(0, con)
        else:
            try:
                con.close()
            except:
                pass

    def __del__(self):
        for con in self.__connections:
            try:
                con.close()
            except:
                pass


redis_pool = RedisConnectPool(REDIS)

if __name__ == '__main__':
    date = rds_sql('select now()')
    if isinstance(date, str):
        print('ERROR: {}'.format(date))
    else:
        print(date)

    with redis_pool.get() as con:
        print(con.keys('*'))
        print(con.get('test_key'))

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值