0、 安装驱动
pip install redis
pip install python-redis
1、 直接连接
redis-py提供
两个类Redis和StrictRedi
s
用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。
redis取出的结果默认是字节,可以使用
decode_responses=True
改成字符串。
import redis
r = redis.Redis(host='127.0.0.1', port=6379, password="123", decode_responses=True, max_connections=None)
r.set('foo', 'Bar')
print(r.get('foo'))
'''
decode_responses=False: b'Bar' <class 'bytes'>
decode_responses=True: Bar <class 'str'>
'''
注:连接redis,加上decode_responses=True,则写入键值对中的value为str类型,不加这个参数写入的则为字节类型
2、 连接池--适用于并发量高场景
redis-py
使用connection pool
来管理对一个redis server的所有连接,
避免每次建立、释放连接的开销
。
默认,每个Redis实例都会维护一个自己的连接池
。
可以直接建立一个连接池,然后作为参数Redis,
这样就可以实现多个Redis实例共享一个连接池。
import redis
kwargs = {
'host': '127.0.0.1',
'port': 6379,
'decode_responses': True,
'retry_on_timeout': 3,
'max_connections': 1024 # 默认2^31
}
pool = redis.ConnectionPool(**kwargs)
r = redis.Redis(connection_pool=pool)
或者:
pool = redis.ConnectionPool(decode_responses=True) # 建立连接池
r = redis.Redis(connection_pool=pool,host='127.0.0.1', port=6379) # 从连接池获取连接
r.set('book', '西游记')
print(r.get('book')) # 西游记
2.1、为什么使用连接池?
Redis是数据库,C/S模式(C/S本身是种远程通信的交互模式),使用它需要建立连接。客户端访问Redis服务器到返回数据给客户端(一次数据请求), 耗时主要花费在两处:1、底层的网络通信,因为每次数据交互需先建立连接;2、Redis数据库处理。前期的底层网络通信占用时长比较多,而连接池可以实现在客户端建立多个连接并且不释放,当需要连接的时候直接从池子获取已经建立的连接,使用完则还给连接池,这免去了数据库连接所占用的时长。
2.2、连接池原理剖析
1、当redis.ConnectionPool 实例化的时候, 做了什么
这个
连接池的实例化其实未做任何真实的redis连接, 仅仅是设置最大连接数, 连接参数和连接类
2、
redis
.
Redis
(
connection_pool
=
pool
)
实例化的时候,,又做了什么
可以看出,使用redis.Redis() 即使不创建连接池, 也会自己创建。到这里, 我们还没有看到什么redis连接真实发生。
3、r.set('book', '西游记'),set操作,这个时候一定会发生redis连接
继续看看execute_command:
连接创建,调用的是ConnectionPool的get_connection:pool.get_connection(command_name, **options)
连接池有可用的连接则直接从连接池获取一个(
connection =
self
._available_connections.pop()),否则创建一个连接(
connection =
self
.make_connection()):
释放连接:pool.release(conn)
连接池对象调用release方法, 将连接从_in_use_connections 放回 _available_connections, 这样后续的连接获取就能再次使用这个连接了。
2.3、redis连接的单例实现
# coding:utf-8
import redis
class RedisDBConfig:
HOST = '127.0.0.1'
PORT = 6379
DBID = 0
def operator_status(func):
"""get operatoration status
"""
def gen_status(*args, **kwargs):
error, result = None, None
try:
result = func(*args, **kwargs)
except Exception as e:
error = str(e)
return {'result': result, 'error': error}
return gen_status
class RedisModel(object):
def __init__(self):
if not hasattr(RedisModel, 'pool'):
RedisModel.create_pool()
self._connection = redis.Redis(connection_pool=RedisModel.pool)
# python中,所有类的实例中的成员变量,都是公用一个内存地址,因此,及时实例化多个RedisCache类,内存中存在的pool也只有一个
@staticmethod
def create_pool():
RedisModel.pool = redis.ConnectionPool(
host=RedisDBConfig.HOST,
port=RedisDBConfig.PORT,
db=RedisDBConfig.DBID)
@operator_status
def set_data(self, key, value):
"""set data with (key, value)
"""
return self._connection.set(key, value)
@operator_status
def get_data(self, key):
"""get data by key
"""
return self._connection.get(key)
@operator_status
def del_data(self, key):
"""delete cache by key
"""
return self._connection.delete(key)
def f1():
r = RedisModel()
print(id(r)) # 3118437616384
def f2():
r1 = RedisModel() # 3118437616384
print(id(r1))
if __name__ == '__main__':
print(RedisModel().set_data('Testkey', "Simple Test")) # {'result': True, 'error': None}
print(RedisModel().get_data('Testkey')) # {'result': b'Simple Test', 'error': None}
print(RedisModel().del_data('Testkey')) # {'result': 1, 'error': None}
print(RedisModel().get_data('Testkey')) # {'result': None, 'error': None}
f1()
f2()
3、参考:
https://blog.csdn.net/dcba2014/article/details/99292430 python redis之连接池的原理
https://blog.csdn.net/moxiaomomo/article/details/27085415 【python】使用redis pool的一种单例实现方式