知道redis是什么,人们常常叫它为缓存数据库,简单来讲这个就是一个存储键值对的数据库。
使用redis的时候,首先,要保证自己的电脑上存在redis服务,也就是安装过redis软件。或者说使用docker下载过镜像文件也是可以的,本人使用的是docker中的redis镜像。其次,在python环境中安装redis(这个redis是客户端启动程序,作用是让python能够连接到Redis服务器中)
一、启动redis服务
bash
# 先创建个网络
sudo docker network create some-redis
# 运行镜像
sudo docker run --name some-redis -d --network some-redis -p 6379:6379 redis:7 redis-server --save 60 1 --loglevel warning
# 以交互的方式进入到redis中
sudo docker run --rm -it --network some-redis redis:7 redis-cli -h some-redis
# 之后每次启动电脑中的redis服务的时候仅仅需要
sudo docker start redis的id
二、在python中连接redis数据库
python
import redis
# 基本连接(同步连接)
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# 基本连接(异步连接)
r = redis.asyncio.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# 连接池(推荐生产环境使用)
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool, decode_responses=True)
# 异步连接+连接池的使用
pool = redis.ConnectionPool.from_url(
'redis://localhost:6379',
max_connections=20,
decode_responses=True
)
r = redis.asyncio.Redis(connection_pool=pool)
# 测试连接
print(r.ping()) # 返回 True 表示连接成功
| 特性 | 直接连接 | 连接池 | 异步连接池 |
|---|---|---|---|
| 性能 | 差(频繁创建) | 好(连接复用) | 极好(非阻塞) |
| 适用场景 | 简单脚本 | 生产环境、多线程 | 异步应用、高并发 |
| 连接管理 | 手动管理 | 自动管理 | 自动管理+协程 |
| 资源消耗 | 高 | 可控 | 低 |
| 复杂度 | 简单 | 中等 | 中等 |
| 并发支持 | 差 | 好 | 极好 |
三、在redis中CRUD
1、字符串
创建数据:set(),setex(),mset()
获取数据:get(),mget()
python
# 设置和获取
r.set('name', 'Alice')
print(r.get('name')) # Alice
# 设置过期时间(秒)
r.setex('token', 3600, 'abc123')
# 批量操作
r.mset({'key1': 'value1', 'key2': 'value2'})
print(r.mget('key1', 'key2'))
2、哈希
存储数据:hset()
获取数据:hget(),hgetall(),hkeys()
删除数据:hdel()
python
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# 存储对象
r.hset('user:1001', mapping={
'name': 'John',
'age': '30',
'email': 'john@example.com'
})
# 获取字段
print(r.hget('user:1001', 'name'))
print(r.hgetall('user:1001'))
# 获取所有字段
print(r.hkeys('user:1001'))
# 从用户哈希中删除 "age" 和 "email" 字段
r.hdel('user:1001', 'age', 'email')
3、集合和有序集合
创建数据:sadd(),其中的第一个str就是集合中的键;zadd()
获取数据:smembers(),zrange()
集合中的其他操作:sinter()交集,
python
# 添加元素
r.sadd('tags', 'python', 'redis', 'database')
# 获取所有成员
print(r.smembers('tags'))
# 集合操作
r.sadd('tags2', 'redis', 'mongodb')
print(r.sinter('tags', 'tags2')) # 交集
# 添加带分数的元素
r.zadd('leaderboard', {'Alice': 100, 'Bob': 85, 'Charlie': 95})
# 获取排名
print(r.zrange('leaderboard', 0, -1, withscores=True))
4、列表
创建数据:lpush(),rpush()
获取数据:lrange()
删除数据:lpop()弹出,lrem()删除列表中的指定值,ltrim()清空指定列表
python
# 添加元素
r.lpush('tasks', 'task1', 'task2', 'task3')
r.rpush('tasks', 'task4')
# 获取元素
print(r.lrange('tasks', 0, -1)) # 获取所有
# 弹出元素
task = r.lpop('tasks')
# 删除列表 "task_queue" 中所有值为 "old_task" 的项
r.lrem('task_queue', 0, 'old_task')
# 清空 "log_list" 列表
r.ltrim('log_list', 0, 0)
四、使用redis
1、pipeline的使用
首先创建pipeline对象,之后将多个命令放入到pipeline中,在通过execute()方法一次性发送到服务器并接收所有结果(结果的顺序与发送的命令的顺序一致)。
python
pipe = r.pipeline()
pipe.set('counter', 0)
pipe.incr('counter')
pipe.get('counter')
result = pipe.execute()
print(result) # [True, 1, '1']
2、发布订阅(Pub/Sub)------其他消息队列还有RabbitMQ\Kafka
发布订阅是一种消息通信模式,主要包含两个角色:发布者和订阅者。
过程:
pubsub():创建专门用于发布订阅对象,这个与Redis客户端分开,专注于消息订阅功能,可以同时订阅多个频道并个管理这些订阅。
subscribe():订阅频道,可以传入多个字符串或由字符串组成的列表。
listen():监听消息,这个是一个生成器,会持续产生消息,每次迭代返回一个消息字典。
publish():发布消息,传入目标频道和消息内容,返回收到此消息的订阅者数量
python
import redis
import threading
import time
# 创建连接
r = redis.Redis(host="localhost",port=6379,decode_responses=True)
def subscriber():
"""订阅者线程"""
pubsub = r.pubsub()
pubsub.subscribe('mychannel')
print("订阅者开始监听...")
for message in pubsub.listen():
if message['type'] == 'message':
print(f"[订阅者] 收到来自 {message['channel']} 的消息: {message['data']}")
def publisher():
"""发布者线程"""
time.sleep(1) # 等待订阅者就绪
for i in range(3):
time.sleep(0.5)
subscribers = r.publish('mychannel', f'消息 #{i+1}')
print(f"[发布者] 发送消息 #{i+1}, 订阅者数量: {subscribers}")
# 启动线程
threading.Thread(target=subscriber, daemon=True).start()
threading.Thread(target=publisher).start()
3、键操作------查询、判断键是否存在,根据键删除内容,根据键设置过期时间
python
# 查询键
keys = r.keys('user:*') # 通配符查询
# 设置过期时间
r.expire('key', 60)
# 判断键是否存在
if r.exists('key'):
print("键存在")
# 同步删除
r.delete('user:1001:profile')
# 异步删除 (推荐用于生产环境删除大对象)
r.unlink('large:hash:key')