概述
参考:python 模块Redis模块,连接Redis数据库
Python 中的 Redis 客户端库允许开发者与 Redis 数据库进行交互。这些库允许在 Python 中连接到 Redis、执行命令以读取或写入数据,并处理 Redis 数据。
以下是一些常见的 Python Redis 客户端库:
redis 库:是 Python 中最常用的 Redis 客户端库之一。它提供了与 Redis 数据库的高度集成,支持 Python 2.x 和 3.x 版本。它具有易于使用的 API,可以轻松地执行 Redis 命令,例如设置值、获取值、处理列表、集合、有序集合等。
注:python 的 redis 库支持直连和哨兵模式,但并不支持集群模式,推荐库:redis-py-cluster
安装命令:
pip install redis
redis-py-cluster 库:是 Python 中的一个用于连接和操作 Redis 集群的客户端库,允许以编程方式连接到 Redis 集群,并执行各种操作,而无需手动管理分片和节点。
Redis 集群是 Redis 数据库的一种分布式部署方式,通过将数据分片存储在不同的 Redis 实例上来提供高可用性和横向扩展性。
主要特点和功能:
- 自动节点发现:允许指定一个或多个节点的初始连接地址,然后会自动发现集群中的其他节点,不需要手动配置每个节点的连接信息。
- 自动分片:可以自动将操作路由到正确的节点和分片,不需要手动计算分片和维护节点列表。
- 高可用性:支持 Redis 集群的故障转移和自动重新连接,确保在节点故障或网络问题后的连续可用性。
- 支持常用 Redis 命令:可以使用执行常见的 Redis 命令,如 SET、GET、HGET、HSET、DEL、INCR、DECR 等。
- 线程安全:是线程安全的,可以在多线程应用程序中使用。
安装命令:
pip install redis-py-cluster
连接 redis 数据库
单点 | 直连模式
同步连接
连接方法:
redis.Redis(host='localhost', # ip地址port=6379, # 端口db=0, # 数据库,默认 0password=None, # 密码single_connection_client=False, # True时,不使用连接池connection_pool=None, # 连接池decode_responses=False, # 默认为False,若设置为True,则在获取数据时将字节解码为字符串(utf-8)socket_timeout=None, # 响应的时间socket_connect_timeout=None, # 建立连接超时时间retry_on_timeout=False, # True时, 命令超时后,将会重试一次, 重试成功则正常返回; 失败则抛出timeout异常;False时直接抛出异常retry_on_error=None, # 重试错误列表max_connections=None, # 最大连接数)
示例:
import redisconnect = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True)connect.set('test','哈哈哈哈')print(connect.get('test'))
异步连接
redis.asyncio.Redis() :异步连接 redis 数据库,参数同 redis.Redis()
示例:
import asyncioimport redis.asyncio as redisasync def run():async with redis.Redis(host='127.0.0.1',port=6379,decode_responses=True) as connect:await connect.set('test','我是异步')result = await connect.get('test')print(result)asyncio.run(run())
哨兵模式
示例:
from redis.sentinel import Sentinelsentinel_nodes = [('192.168.1.110', 16380), ('192.168.1.110', 16381), ('192.168.1.110', 16382)]sentinel = Sentinel(sentinel_nodes, sentinel_kwargs={'password': '123456'}, db=0, socket_timeout=0.5)master = sentinel.master_for('mymaster', password='123456')slave = sentinel.slave_for('mymaster', password='123456')print(master.llen('test'))
集群模式
示例:
from rediscluster import StrictRedisClusterredis_nodes = [{'host':'192.168.1.110','port':13790}, {'host':'192.168.1.110','port':13791}, {'host':'192.168.1.110','port':13793}, {'host':'192.168.1.120','port':13794}]redisconn = StrictRedisCluster(startup_nodes=redis_nodes, decode_responses=True, password='123456')redisconn.set("name", "helloworld")print("My name is: ", redisconn.get('name'))
redis.connect 常用方法
注:以下方法,异步需要使用 async await
字符串操作
设置值
- set(name, value, ex=None, px=None, nx=False, xx=False) :设置指定 key 的值
- name :键名
- value :键对应的值
- ex :可选,设置键的过期时间,单位是秒
- px :可选,设置键的过期时间,单位是毫秒
- nx :可选,默认为 False,如果设置为 True,只有当键不存在时才设置值
- xx :可选,默认为 False,如果设置为 True,只有当键已存在时才设置值
- setnx(name, value) :设置值,只有 name 不存在时,执行设置操作
- setex(name, time, value)) :设置值
- time :过期时间(秒)
- psetex(name, time_ms, value) :设置值
- time_ms :过期时间(毫秒)
- mset({name1:value1, name2:value2, name3:value3, …}) :批量设置值
获取值、删除值
get(name) :获取指定 key 的值
- name:键名
mget(name1, name2, name3, …) :批量获取值
getrange(name, start, end) :获取部分值
- start :开始 index
- end :结束 index,不包含结束 index 的字符
getset(name,value) :设置新值,并获取旧值
*delete(names) :删除一个或多个 key
- names :要删除的键名
其他
- setrange(name, offset, value) :从指定字符串索引 offset 开始,替换字符串
- append(name, value) :在原有字符基础上追加字符
- strlen(name) :返回 name 对应值的字节长度(一个汉字 3 个字节)
- incr(name, amount=1) :自增 name 对应的值,当 name 不存在时,则创建 name=amount,否则,则自增
- decr(name, amount=1) :自减 name 对应的值,当 name 不存在时,则创建 name=amount,否则,则自减
- incrby(name, amount=1) :在原有数值基础上加上一定的数值,当 name 不存在时,则创建 name=amount
- decrby(name, amount=1) :在原有数值基础上减去一定的数值,当 name 不存在时,则创建 name=amount
- incrbyfloat(name, amount=1.0) :自增 name 对应的值,当 name 不存在时,则创建 name=amount,否则,则自增。
- setbit(name, offset, value) :对 name 对应值的二进制表示的位进行操作
- getbit(name, offset) :获取 name 对应的值的二进制表示中的某位的值 (0 或1 )
- bitcount(key, start=None, end=None) :获取 name 对应的值的二进制表示中 1 的个数
列表操作
- *lpush(name, values) :将一个或多个值插入列表头部(左侧)
- name :列表名
- values :一个或多个值
- *rpush(name, values) :将一个或多个值插入列表尾部(右侧)
- lpushx(name, value) :向已有 name 的列表的左边添加元素,没有的话无法创建
- rpushx(name, value) :向已有 name 的列表的右边添加元素,没有的话无法创建
- linsert(name, where, refvalue, value) :在name对应的列表的某一个值前或后插入一个新值
- where :BEFORE或AFTER
- refvalue :标杆值,即:在它前后插入数据
- value :要插入的数据
- lset(name, index, value) :指定索引位置重新赋值
- lrange(name, start, end) :在 name 对应的列表中取出 start – end 索引之间的值,包含 end
- llen(name) :获取 name 列表中值的数量
- lindex(index) :取值(根据索引号取值)
- lpop(name) :移除并返回列表左侧的第一个元素
- rpop(name) :移除并返回列表右侧的第一个元素
- *blpop(keys, timeout) :将多个列表排列,按照从左到右去移除对应列表的元素
- *brpop(keys, timeout) :将多个列表排列,按照从右到左去移除各个列表内的元素
- rpoplpush(src, dst, timeout ) :从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
- src :要取数据的列表的 name
- dst :要添加数据的列表的 name
- brpoplpush(src, dst, timeout=0) :从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
- timeout :当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
- lrem(name, value, num) :删除指定的 value,num 为负数时从后向前删除
- ltrim(name, start, end) :在 name 对应的列表中移除没有在 start – end 索引之间的值
哈希操作
- hset(name, key, value) :在哈希表中设置字段的值
- name :哈希表名
- key :字段名
- value :字段的值
- hsetnx(name, key, value) :设置值,只有 name 不存在时,执行设置操作
- hmset(name, {key1:value1, key2:value2, key3:value3, …}) :批量添加值
- hget(name, key) :获取哈希表中 key 字段的值
- *hmget(name, keys) :获取哈希表中一个或多个字段的值
- hgetall(name) :取出所有的值
- hkeys(name) :获取所有的 key
- hvals(name) :获取所有的 value
- hlen(name) :获取 hash 中键值对的个数
- hstrlen(name, key) :获取指定 key 值的长度
- *hdel(name, keys) :删除哈希表中一个或多个字段
- hexists(name, key) :判断 hash 中 key 是否存在
- hincrby(name, key, amount=1) :自增自减数(正数自增,负数自减)
- hincrbyfloat(name, key, amount=1.0) :自增自减浮点数(正浮点数自增,负浮点数自减)
- hscan(name, cursor=0, match=None, count=None) :取值查看–分片读取
- cursor :游标(基于游标分批取获取数据)
- match :匹配指定 key,默认 None,表示所有的 key
- count :每次分片最少获取个数,默认 None,表示采用 Redis 的默认分片个数
- hscan_iter(name, match=None, count=None) :利用 yield 封装 hscan 创建生成器,实现分批去 redis 中获取数据
- match :匹配指定 key,默认 None,表示所有的key
- count :每次分片最少获取个数,默认 None,表示采用 Redis 的默认分片个数
集合操作
- sadd(name, values) :向集合添加一个或多个元素
- name :集合名
- values :一个或多个元素
- smembers(name) :获取集合中的所有元素
- scard(name) :获取name集合中的个数
- srandmember(namem,num) :从集合随机取出 num 个元素
- srem(name, values) :从集合中删除一个或多个元素
- spop(name) :从集合移除一个成员,并将其返回,说明一下,集合是无序的,所有是随机删除的
- smove(src, dst, value) :将某个成员从一个集合中移动到另外一个集合
- sismember(name, value) :检查 value 是否是 name 对应的集合的成员,结果为 True 和 False
- sdiff(keys) :获取多个集合的差集
- *sdiffstore(dest, keys) :获取多个集合的差集,并存进一个新的集合
- sinter(keys) :获取多个集合的交集
- *sinterstore(dest, keys) :获取多个集合的差集,并存进一个新的集合
- sunion(keys) :获取多个集合的并集
- *sunionstore(dest, keys) :获取多个集合的并集,并存进一个新的集合
有序集合操作
zadd(name, mapping) :向有序集合添加一个或多个成员
- name :有序集合名
- mapping :成员及其分数的字典
其他可选参数:
nx :强制 ZADD 只创建新元素而不更新已经存在的元素的分数。默认 False
xx :强制 ZADD 只更新已经存在的元素的分数存在。不会添加新元素。默认 False
ch :将返回值修改为已更改的元素数。更改的元素包括添加的新元素和元素谁的分数变了。默认 False
incr :修改 ZADD 的行为像 ZINCRBY。默认 False
在这种模式下,只有 a 可以指定单个元素/分数对,分数是数量现有的分数将增加到。
使用此模式时 ZADD 的返回值将是元素的新分数。
lt :仅在新分数小于时更新现有元素当前分数。这个标志不会阻止添加新元素。默认 False
gt :仅在新分数大于时更新现有元素当前分数。这个标志不会阻止添加新元素。默认 False
zrange(name, start, end) :按分数范围获取有序集合的成员
- start :分数的起始值
- end :分数的结束值
其他可选参数:
- desc :排序规则,默认按照分数从小到大排序。默认 False
- withscores :是否获取元素的分数,默认只获取元素的值。默认 False
- score_cast_func :对分数进行数据转换的函数。默认 float
zrevrange(name, start, end) :从大到小排序(同 zrange 默认排序,集合是从大到小排序的)
其他可选参数:
- withscores :是否获取元素的分数,默认只获取元素的值 。默认 False
- score_cast_func :对分数进行数据转换的函数。默认 float
zrangebyscore(name, min, max) :按照分数范围获取 name 对应的有序集合的元素
- min :最小值
- max :最大值
其他可选参数:
- start :有序集合索引起始位置(非分数)。默认 None
- num :获取数量。默认 None
- withscores :是否获取元素的分数,默认只获取元素的值 。默认 False
- score_cast_func :对分数进行数据转换的函数。默认 float
zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float) :按照分数范围获取有序集合的元素并排序(默认从大到小排序)
zscan(name, cursor=0, match=None, count=None, score_cast_func=float) :获取所有元素
zscan_iter(name, match=None, count=None, score_cast_func=float) :获取所有元素–迭代器
zcard(name) :获取元素集合中的个数
*zrem(name, values) :从有序集合中删除一个或多个成员
zremrangebyrank(name, min, max) :根据索引范围删除
zremrangebyscore(name, min, max) :根据分数范围删除
zcount(name, min, max) :获取 name 对应的有序集合中分数在 [min,max] 之间的个数
zincrby(name, value, amount) :自增自减数(正数自增,负数自减)
zrank(name, value) :获取索引,按照分数顺序(从小到大)
zrevrank(name, value) :获取索引,按照倒序(从大到小)
zscore(name, value) :获取对应值的分数
键的相关通用操作
- dbsize() :返回服务器中的键数
- keys(pattern) :返回匹配 “pattern” 的键列表,不传返回全部
- scan_iter(match, count) :返回匹配 match 键迭代器,不传返回全部
- move(name, db) :将键 name 移动到另一个数据库 db
- flushall(asynchronous=False) :删除当前主机上所有数据库中的所有键,asynchronous 是否异步
- flushdb(asynchronous=False) :删除当前数据库中的所有键,asynchronous 是否异步
- dump(name) :返回存储在指定键处的值的序列化版本
- type(name) :返回键类型
- rename(src, dst) :重命名键 src 为 dst
- renamex(src, dst) :如果 dst 不存在,则将 src 重命名为 dst
- exists(names) :一个或多个由 “names” 指定的键是是否存在
过期时间
- expire(name, time, nx=False, xx=False, gt=False, lt=False) :为键 name 设置过期时间
- time :过期时间,单位:秒
- nx :仅当密钥没有过期时设置过期
- xx :仅当密钥已存在过期时才设置过期
- gt :仅当新过期时间大于当前过期时间时设置过期时间
- lt :仅在新到期时间小于当前到期时间时设置到期时间
- expireat(name, when, nx=False, xx=False, gt=False, lt=False) :为键 name 设置过期时间
- when :可以表示为整数表示 unix 时间或 Python datetime 对象
- pexpire(name, time, nx=False, xx=False, gt=False,lt=False) :为键 name 设置过期时间
- time :过期时间,单位:毫秒
- ttl(name) :返回键 name 到期前的秒数
- pttl(name) :返回键 name 到期前的毫秒数
- persist(name) :删除 name 的过期
- time() :获取 redis 服务端的当前时间。它返回一个包含两个元素的数组,其中第一个元素是当前时间的秒数(自 Unix 时间戳的起始点以来的秒数),第二个元素是当前时间的微秒数。
连接状态和数据持久化
- close() :关闭 Redis 连接
- ping() :判断服务器是否连接成功
- select(index) :切换数据库
- save() :持久化数据
- bgsave() :异步持久化数据
- shutdonw(save=False, nosave=False, now=False, force=False, abort=False) :如果 Redis 配置了持久化,数据将在关机前被刷新
- save :会强制执行 DB 保存操作
- nosave :将阻止数据库保存操作,即使有一个或多个保存点配置
- now :跳过等待滞后副本,即它绕过了第一步关机顺序
- force :忽略任何通常会阻止服务器退出的错误
- abort :取消正在进行的关机,不能与其他标志结合使用
- lastsave() :获取 Redis 数据库中最后一次成功执行持久化操作的时间戳(一个 Python datetime 对象),也就是最后一次生成 RDB 快照的时间。
连接池
redis.ConnectionPool(option)
option参数大部分和 redis.Redis 一致
连接池的原理是,通过预先创建多个连接,当进行 redis 操作时,直接获取已经创建的连接进行操作,而且操作完成后,不会释放,用于后续的其他 redis 操作,这样就达到了避免频繁的 redis 连接创建和释放的目的,从而提高性能。
redis 模块采用 ConnectionPool 来管理对 redis server 的所有连接
import redispool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True)connect = redis.Redis(connection_pool=pool)connect.set('name','数据库0')print(connect.get('name'))
redis.BlockingConnectionPool(option)
option 参数大部分和 redis.Redis 一致
BlockingConnectionPool 和 ConnectionPool 功能是一样的,但是是线程安全的,在多线程的环境下,建议用BlockingConnectionPool,比如 gunicorn 使用了多线程的 worker。同时,当所有连接都在使用时,获取可用连接不会抛异常,而是可以设置等待时间。