MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python使用redis-py库连接Redis数据库

2023-11-052.4k 阅读

安装 redis - py 库

在使用 redis - py 库连接 Redis 数据库之前,首先需要确保该库已经安装在你的 Python 环境中。如果你使用的是 pip 包管理器,安装 redis - py 库非常简单,只需在命令行中执行以下命令:

pip install redis

如果你使用的是 conda 环境,可以使用以下命令进行安装:

conda install -c conda - forge redis

安装完成后,就可以在 Python 代码中引入 redis 模块来连接和操作 Redis 数据库了。

基本连接

在 Python 中使用 redis - py 连接 Redis 数据库,最基本的方式如下:

import redis

# 创建 Redis 连接对象
r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置一个键值对
r.set('name', 'John')

# 获取键对应的值
name = r.get('name')
print(name.decode('utf - 8'))

在上述代码中:

  1. 首先通过 import redis 导入 redis 模块。
  2. 然后使用 redis.Redis 类创建一个 Redis 连接对象 r。这里指定了 Redis 服务器的主机为 localhost(如果 Redis 服务器运行在其他主机上,需要替换为相应的主机地址),端口为默认的 6379,并选择使用 db 0 数据库(Redis 支持多个逻辑数据库,编号从 0 开始)。
  3. 使用 r.set('name', 'John') 方法在 Redis 中设置一个键为 name,值为 John 的键值对。
  4. 通过 r.get('name') 获取键 name 对应的值。需要注意的是,redis - py 获取的值是字节类型,所以这里使用 decode('utf - 8') 将其转换为字符串类型并打印出来。

连接池的使用

在实际应用中,尤其是在高并发的场景下,频繁地创建和销毁 Redis 连接是非常消耗资源的。为了提高性能和资源利用率,可以使用连接池。redis - py 提供了 ConnectionPool 类来实现连接池功能。以下是使用连接池的示例代码:

import redis

# 创建连接池
pool = redis.ConnectionPool(host='localhost', port=6379, db = 0)

# 通过连接池创建 Redis 连接对象
r = redis.Redis(connection_pool = pool)

# 设置一个键值对
r.set('age', 30)

# 获取键对应的值
age = r.get('age')
print(int(age))

在这个例子中:

  1. 首先创建了一个 ConnectionPool 对象 pool,同样指定了 Redis 服务器的主机、端口和数据库。连接池会预先创建一定数量的连接,并在需要时复用这些连接。
  2. 然后通过 redis.Redis(connection_pool = pool) 创建 Redis 连接对象 r,这样 r 就会从连接池 pool 中获取连接来执行 Redis 命令。

密码认证

如果你的 Redis 服务器设置了密码,在连接时需要进行密码认证。在 redis - py 中,认证非常简单,只需要在创建连接对象时传入 password 参数即可。示例代码如下:

import redis

# 创建 Redis 连接对象并进行密码认证
r = redis.Redis(host='localhost', port=6379, db = 0, password='your_password')

# 设置一个键值对
r.set('email', 'john@example.com')

# 获取键对应的值
email = r.get('email')
print(email.decode('utf - 8'))

在上述代码中,通过 password='your_password' 传入了 Redis 服务器的密码,这样才能成功连接并操作 Redis 数据库。

操作字符串类型数据

Redis 中的字符串类型是最基本的数据类型,redis - py 提供了丰富的方法来操作字符串类型的数据。

设置值

除了前面使用过的 set 方法外,redis - py 还提供了一些其他设置值的方法。

  • setex 方法:设置带有过期时间的键值对
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置键为 'token',值为 '123456',过期时间为 60 秒
r.setex('token', 60, '123456')

在上述代码中,setex 方法的第一个参数是键 'token',第二个参数是过期时间(单位为秒),第三个参数是值 '123456'。这意味着 'token' 这个键值对会在 60 秒后自动过期并从 Redis 中删除。

  • psetex 方法:设置带有过期时间(以毫秒为单位)的键值对
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置键为 'timestamp',值为 '2023 - 10 - 01 12:00:00',过期时间为 1000 毫秒
r.psetex('timestamp', 1000, '2023 - 10 - 01 12:00:00')

这里 psetex 方法与 setex 类似,只是过期时间是以毫秒为单位。

获取值

获取字符串类型值最常用的方法是 get 方法。此外,还有以下相关方法。

  • mget 方法:批量获取多个键的值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置多个键值对
r.set('name1', 'Alice')
r.set('name2', 'Bob')

# 批量获取多个键的值
names = r.mget(['name1', 'name2'])
for name in names:
    print(name.decode('utf - 8'))

在上述代码中,通过 mget 方法一次性获取了 'name1''name2' 两个键的值,提高了获取多个值的效率。

  • getrange 方法:获取字符串的子串
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

r.set('message', 'Hello, Redis!')

# 获取从索引 7 开始到末尾的子串
substring = r.getrange('message', 7, -1)
print(substring.decode('utf - 8'))

getrange 方法的第一个参数是键,第二个参数是子串的起始索引(从 0 开始),第三个参数是子串的结束索引(-1 表示到字符串末尾)。这里获取了 'message' 键对应字符串从索引 7 开始到末尾的子串。

对字符串进行增减操作

如果字符串的值是数字类型,redis - py 还提供了对其进行增减操作的方法。

  • incr 方法:将键对应的值增加 1
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置键为 'counter',初始值为 10
r.set('counter', 10)

# 将 'counter' 的值增加 1
r.incr('counter')

# 获取 'counter' 的值
new_counter = r.get('counter')
print(int(new_counter))
  • incrby 方法:将键对应的值增加指定的整数
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

r.set('score', 50)

# 将'score' 的值增加 20
r.incrby('score', 20)

# 获取'score' 的值
new_score = r.get('score')
print(int(new_score))
  • decr 方法:将键对应的值减少 1
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

r.set('stock', 100)

# 将'stock' 的值减少 1
r.decr('stock')

# 获取'stock' 的值
new_stock = r.get('stock')
print(int(new_stock))
  • decrby 方法:将键对应的值减少指定的整数
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

r.set('quantity', 50)

# 将 'quantity' 的值减少 10
r.decrby('quantity', 10)

# 获取 'quantity' 的值
new_quantity = r.get('quantity')
print(int(new_quantity))

操作哈希类型数据

哈希类型在 Redis 中用于存储字段和值的映射关系,类似于 Python 中的字典。redis - py 提供了很多操作哈希类型数据的方法。

设置哈希字段值

  • hset 方法:设置单个哈希字段的值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 设置哈希键为 'user:1',字段为 'name',值为 'Tom'
r.hset('user:1', 'name', 'Tom')
  • hmset 方法:设置多个哈希字段的值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

data = {
    'name': 'Jerry',
    'age': 25,
    'email': 'jerry@example.com'
}

# 设置哈希键为 'user:2' 的多个字段值
r.hmset('user:2', data)

在上述代码中,通过 hmset 方法一次性设置了 'user:2' 这个哈希键的多个字段值。

获取哈希字段值

  • hget 方法:获取单个哈希字段的值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取哈希键为 'user:1',字段为 'name' 的值
name = r.hget('user:1', 'name')
print(name.decode('utf - 8'))
  • hmget 方法:获取多个哈希字段的值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取哈希键为 'user:2' 的 'name' 和 'email' 字段的值
fields = ['name', 'email']
values = r.hmget('user:2', fields)
for value in values:
    print(value.decode('utf - 8'))
  • hgetall 方法:获取哈希键的所有字段和值
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取哈希键为 'user:2' 的所有字段和值
all_data = r.hgetall('user:2')
for key, value in all_data.items():
    print(key.decode('utf - 8'), ':', value.decode('utf - 8'))

获取哈希字段数量

可以使用 hlen 方法获取哈希键中字段的数量。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取哈希键为 'user:2' 的字段数量
field_count = r.hlen('user:2')
print(field_count)

判断哈希字段是否存在

使用 hexists 方法可以判断哈希键中某个字段是否存在。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 判断哈希键为 'user:2' 的 'age' 字段是否存在
exists = r.hexists('user:2', 'age')
print(exists)

操作列表类型数据

Redis 中的列表是一个双向链表结构,可以在列表的两端进行插入和删除操作。redis - py 提供了丰富的方法来操作列表类型数据。

在列表两端插入元素

  • lpush 方法:在列表头部插入元素
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 在列表 'fruits' 的头部插入元素 'apple'
r.lpush('fruits', 'apple')
  • rpush 方法:在列表尾部插入元素
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 在列表 'fruits' 的尾部插入元素 'banana'
r.rpush('fruits', 'banana')

从列表两端弹出元素

  • lpop 方法:从列表头部弹出元素
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 从列表 'fruits' 的头部弹出元素
fruit = r.lpop('fruits')
print(fruit.decode('utf - 8'))
  • rpop 方法:从列表尾部弹出元素
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 从列表 'fruits' 的尾部弹出元素
fruit = r.rpop('fruits')
print(fruit.decode('utf - 8'))

获取列表长度

使用 llen 方法可以获取列表的长度。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取列表 'fruits' 的长度
length = r.llen('fruits')
print(length)

获取列表指定范围的元素

使用 lrange 方法可以获取列表指定范围的元素。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 在列表 'numbers' 中插入多个元素
r.rpush('numbers', 1)
r.rpush('numbers', 2)
r.rpush('numbers', 3)
r.rpush('numbers', 4)
r.rpush('numbers', 5)

# 获取列表 'numbers' 中索引从 1 到 3 的元素
sub_list = r.lrange('numbers', 1, 3)
for number in sub_list:
    print(int(number))

在上述代码中,lrange 方法的第一个参数是列表键,第二个参数是起始索引(从 0 开始),第三个参数是结束索引(包含该索引位置的元素)。

操作集合类型数据

Redis 的集合是无序的、唯一的元素集合。redis - py 提供了一系列操作集合类型数据的方法。

添加元素到集合

使用 sadd 方法可以向集合中添加元素。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 向集合 'colors' 中添加元素'red'
r.sadd('colors','red')

从集合中移除元素

使用 srem 方法可以从集合中移除元素。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 从集合 'colors' 中移除元素'red'
r.srem('colors','red')

获取集合中的所有元素

使用 smembers 方法可以获取集合中的所有元素。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取集合 'colors' 中的所有元素
members = r.smembers('colors')
for member in members:
    print(member.decode('utf - 8'))

获取集合元素数量

使用 scard 方法可以获取集合中元素的数量。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取集合 'colors' 中元素的数量
count = r.scard('colors')
print(count)

集合间的操作

  • 交集:使用 sinter 方法可以获取多个集合的交集。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 向集合'set1' 中添加元素
r.sadd('set1', 1)
r.sadd('set1', 2)
r.sadd('set1', 3)

# 向集合'set2' 中添加元素
r.sadd('set2', 2)
r.sadd('set2', 3)
r.sadd('set2', 4)

# 获取集合'set1' 和'set2' 的交集
intersection = r.sinter('set1','set2')
for value in intersection:
    print(int(value))
  • 并集:使用 sunion 方法可以获取多个集合的并集。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取集合'set1' 和'set2' 的并集
union = r.sunion('set1','set2')
for value in union:
    print(int(value))
  • 差集:使用 sdiff 方法可以获取多个集合的差集。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取集合'set1' 与'set2' 的差集
difference = r.sdiff('set1','set2')
for value in difference:
    print(int(value))

操作有序集合类型数据

Redis 的有序集合与集合类似,也是唯一元素的集合,但每个元素都会关联一个分数(score),通过分数来对元素进行排序。redis - py 提供了相应的方法来操作有序集合。

添加元素到有序集合

使用 zadd 方法可以向有序集合中添加元素及其分数。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 向有序集合 'ranking' 中添加元素 'Alice',分数为 85
r.zadd('ranking', {'Alice': 85})

获取有序集合中指定范围的元素

  • 按分数范围获取:使用 zrangebyscore 方法可以获取有序集合中指定分数范围的元素。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 向有序集合 'ranking' 中添加多个元素及其分数
r.zadd('ranking', {'Alice': 85, 'Bob': 90, 'Charlie': 78})

# 获取分数在 80 到 90 之间的元素
result = r.zrangebyscore('ranking', 80, 90)
for member in result:
    print(member.decode('utf - 8'))
  • 按索引范围获取:使用 zrange 方法可以获取有序集合中指定索引范围的元素。
import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取有序集合 'ranking' 中索引从 0 到 1 的元素
result = r.zrange('ranking', 0, 1)
for member in result:
    print(member.decode('utf - 8'))

获取有序集合元素数量

使用 zcard 方法可以获取有序集合中元素的数量。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取有序集合 'ranking' 中元素的数量
count = r.zcard('ranking')
print(count)

获取有序集合中元素的分数

使用 zscore 方法可以获取有序集合中某个元素的分数。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 获取有序集合 'ranking' 中 'Alice' 的分数
score = r.zscore('ranking', 'Alice')
print(score)

事务操作

Redis 支持事务,redis - py 也提供了相应的功能来实现事务操作。事务可以将多个命令打包在一起执行,要么所有命令都执行成功,要么都不执行。

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 开启事务
pipe = r.pipeline()

try:
    # 在事务中添加命令
    pipe.set('key1', 'value1')
    pipe.set('key2', 'value2')

    # 执行事务
    pipe.execute()
except redis.RedisError as e:
    print(f"事务执行出错: {e}")
    # 可以选择回滚事务,不过 Redis 事务自动回滚
    pipe.reset()

在上述代码中:

  1. 通过 r.pipeline() 开启一个事务管道 pipe
  2. 使用 pipe 对象添加需要执行的 Redis 命令,如 pipe.set('key1', 'value1')pipe.set('key2', 'value2')
  3. 最后通过 pipe.execute() 执行事务中的所有命令。如果在执行过程中出现错误,会捕获 redis.RedisError 异常。虽然 Redis 事务会自动回滚,但在 Python 代码中可以根据需要进行相应的处理,比如这里使用 pipe.reset() 重置管道。

发布与订阅

Redis 提供了发布订阅功能,redis - py 也支持这一特性。通过发布订阅,客户端可以订阅一个或多个频道,当有消息发布到这些频道时,订阅者会收到相应的消息。

订阅频道

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 创建发布订阅对象
pubsub = r.pubsub()

# 订阅频道 'news'
pubsub.subscribe('news')

# 监听消息
for message in pubsub.listen():
    if message['type'] =='message':
        print(f"收到消息: {message['data'].decode('utf - 8')}")

在上述代码中:

  1. 首先通过 r.pubsub() 创建一个发布订阅对象 pubsub
  2. 然后使用 pubsub.subscribe('news') 订阅频道 'news'
  3. 通过 for message in pubsub.listen() 循环监听频道上发布的消息。当接收到消息时,判断消息类型,如果是 'message' 类型,则打印消息内容。

发布消息到频道

import redis

r = redis.Redis(host='localhost', port=6379, db = 0)

# 发布消息到频道 'news'
r.publish('news', '新的新闻报道来了!')

在这个示例中,使用 r.publish('news', '新的新闻报道来了!') 将消息 '新的新闻报道来了!' 发布到频道 'news' 上,订阅了该频道的客户端会收到这条消息。

通过以上对 redis - py 库的详细介绍,你已经掌握了在 Python 中使用 redis - py 连接 Redis 数据库并进行各种数据操作、事务处理以及发布订阅等功能的方法。在实际项目中,可以根据具体需求灵活运用这些知识来充分发挥 Redis 的优势。