Redis - Python 客户端基本使用指南

概述

参考: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, 				# 数据库,默认 0
        password=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 redis
    
    connect = 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 asyncio
    import redis.asyncio as redis
    
    async 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 Sentinel
    
    sentinel_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 StrictRedisCluster
    
    redis_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 redis
    
    pool = 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。同时,当所有连接都在使用时,获取可用连接不会抛异常,而是可以设置等待时间。