第三方 Python 库 redis-py + hiredis 的使用
一、背景:为什么 Python 开发者需要关注 Redis 客户端库?
做过 Web 开发的同学,对 Redis 一定不陌生。无论是做缓存、会话管理、消息队列,还是排行榜、计数器,Redis 几乎是后端架构里的"标配组件"。
但问题来了------Python 怎么跟 Redis 打交道?
答案是:通过客户端库。Python 生态里最主流的 Redis 客户端就是 redis-py,它是 Redis 官方维护的 Python SDK,几乎所有的 Python 项目操作 Redis 都在用它。
而 hiredis,则是另一个经常被提起的名字。很多教程里会告诉你"装上 hiredis 能让 redis-py 跑得更快",但很少有人把两者的关系和原理讲清楚。
这篇文章就来把这件事说透:redis-py 和 hiredis 到底是什么关系?为什么要一起用?怎么用?
二、概念厘清:redis-py 和 hiredis 分别是什么?
2.1 redis-py ------ Python 的 Redis "翻译官"
redis-py 是 Redis 官方出品的 Python 客户端库,用纯 Python 编写。它的职责很明确:
- 把你在 Python 里写的
r.set('name', 'Tom')翻译成 Redis 能理解的 RESP 协议报文 - 把 Redis 返回的二进制响应解析成 Python 能用的数据类型(bytes、str、int、list 等)
你可以把它想象成一个翻译官:你用 Python 说话,Redis 用 RESP 协议说话,redis-py 负责两边互译。
python
import redis
# 创建连接
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# 操作 Redis 就像操作 Python 字典一样简单
r.set('name', 'Tom')
print(r.get('name')) # 输出: Tom
2.2 hiredis ------ 用 C 写的"高性能翻译引擎"
hiredis 是 Redis 官方用 C 语言 编写的客户端库。它的定位不是给 Python 开发者直接用的,而是作为一个底层引擎。
hiredis 最核心的价值在于它的回复解析器(Reply Parser)------它用 C 实现了一套高效的 RESP 协议解析逻辑,能把 Redis 返回的原始字节流快速解析成结构化数据。
打个比方:
- redis-py 自带的解析器是用 Python 写的,相当于一个普通翻译
- hiredis 的解析器是用 C 写的,相当于一个同声传译设备------速度更快、效率更高
2.3 两者的关系:redis-py 是外壳,hiredis 是加速引擎
关键结论:redis-py 和 hiredis 不是竞争关系,而是合作关系。
redis-py 从 3.x 版本开始就内置了对 hiredis 的支持。当系统中安装了 hiredis(>= 1.0),redis-py 会自动切换使用 hiredis 的 C 语言解析器来处理 Redis 响应,而不需要你修改任何代码。
用一张表来总结:
| 对比维度 | redis-py | hiredis |
|---|---|---|
| 语言 | Python | C |
| 角色 | 完整的 Redis 客户端 SDK | 底层协议解析引擎 |
| 能否独立使用 | 能,开箱即用 | 能,但需要 C 编程 |
| 在 Python 中的作用 | 主角,负责所有 Redis 操作 | 配角,只负责加速响应解析 |
| 是否需要改代码 | --- | 不需要,redis-py 自动识别并启用 |
三、方案选择:要不要装 hiredis?
3.1 只用 redis-py(纯 Python 模式)
redis-py 自带一个纯 Python 实现的响应解析器,功能完全够用。如果你的场景是:
- 数据量不大
- 对延迟不敏感
- 不想引入 C 扩展依赖
那么只装 redis-py 就够了:
bash
pip install redis
3.2 redis-py + hiredis(加速模式)
如果你的场景是:
- 高并发,每秒处理大量 Redis 命令
- 需要解析大量数据(比如
HGETALL一个有几万个 field 的 Hash) - 对响应时间有要求
那就推荐安装 hiredis:
bash
pip install "redis[hiredis]"
这个命令会同时安装 redis-py 和 hiredis,而且 redis-py 会自动检测并启用 hiredis 解析器,无需任何代码改动。
3.3 性能差距有多大?
hiredis 解析器相比纯 Python 解析器,通常能带来 2~10 倍 的解析速度提升,具体取决于响应数据的大小和复杂度。数据量越大、结构越复杂(比如嵌套的数组),hiredis 的优势越明显。
不过要注意:hiredis 只优化了"响应解析"这一环节。如果你的瓶颈在网络延迟或 Redis 本身的执行速度,装 hiredis 的提升就不会那么显著。
四、环境搭建与配置
4.1 前置条件
- Python 3.12+(本文开发环境)
- Redis 服务端 7.2+(推荐)
- pip 包管理器
4.2 关于 Python 版本的说明
本文的开发环境基于 Python 3.12,选择这个版本有几个考量:
Python 3.12 的主要改进
Python 3.12 是一个值得关注的版本,带来了不少实质性的提升:
- 性能优化:CPython 解释器本身的执行效率有了明显提升,整体性能比 3.11 提升约 5%
- 类型提示增强 :
typing模块进一步完善,支持更灵活的泛型写法 - 错误信息更友好:报错提示更加精准,调试体验好了不少
- 移除废弃模块 :
distutils等老旧模块被正式移除
对 redis-py 的影响
结论:完全兼容,放心使用。
redis-py 6.2.0 要求 Python 3.9+,Python 3.12 完全满足要求。而且 redis-py 的代码风格也在跟进新版 Python 的特性,比如类型注解的写法更规范了。
bash
# 在 Python 3.12 环境下安装 redis-py,没有任何兼容性问题
pip install redis
对 hiredis 的影响
结论:使用 hiredis 2.0+ 版本即可。
hiredis 是 C 扩展包,需要编译后才能在 Python 中使用。Python 3.12 对 C API 做了一些调整(比如移除了一些废弃的 API),所以 hiredis 需要相应更新才能兼容。
好消息是,hiredis 2.0+ 已经适配了 Python 3.12 的 C API 变化,直接安装就行:
bash
pip install "redis[hiredis]"
如果你之前在旧版本 Python 下安装过 hiredis,升级到 Python 3.12 后建议重新安装:
bash
pip install --force-reinstall "redis[hiredis]"
版本对应关系速查
| Python 版本 | redis-py 要求 | hiredis 建议版本 | 兼容性 |
|---|---|---|---|
| 3.9 ~ 3.11 | >= 6.2.0 | >= 1.0 | 完全兼容 |
| 3.12+ | >= 6.2.0 | >= 2.0 | 完全兼容(推荐) |

小提示:如果你是新项目,直接用 Python 3.12 + redis-py 最新版 + hiredis 2.0+ 就是最稳的组合。
4.3 启动 Redis
用 Docker 启动一个 Redis 实例最省事:
bash
# Redis 8.0+
docker run -p 6379:6379 -it redis:latest
# Redis 8.0 以下
docker run -p 6379:6379 -it redis/redis-stack:latest
4.4 安装 redis-py(两种方式)
方式一:只装 redis-py
bash
pip install redis
方式二:redis-py + hiredis 加速(推荐)
bash
pip install "redis[hiredis]"
安装完成后,可以通过以下方式验证 hiredis 是否生效:
python
import redis
print(redis.__version__) # 查看 redis-py 版本
# 检查 hiredis 是否可用
try:
import hiredis
print(f"hiredis 版本: {hiredis.__version__}")
print("hiredis 解析器已启用,性能加速生效!")
except ImportError:
print("hiredis 未安装,使用纯 Python 解析器")
4.5 建立连接
redis-py 提供了多种连接方式,从简单到复杂依次是:
直接连接
python
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
带解码的连接(推荐)
默认情况下,redis-py 返回的是 bytes 类型(如 b'Tom')。加上 decode_responses=True 后,返回的就是 Python 字符串了:
python
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
r.set('name', 'Tom')
print(r.get('name')) # 输出: Tom(字符串)
print(type(r.get('name'))) # <class 'str'>
使用连接池
在生产环境中,建议使用连接池来管理连接,避免频繁创建和销毁连接的开销:
python
import redis
# 创建连接池
pool = redis.ConnectionPool(
host='localhost',
port=6379,
db=0,
decode_responses=True,
max_connections=20 # 最大连接数
)
# 从连接池获取连接
r = redis.Redis(connection_pool=pool)
五、实战:redis-py 常用操作
以下示例均基于 redis-py 官方文档,使用 decode_responses=True 以便输出更直观。
5.1 字符串操作
python
import redis
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# SET / GET
r.set('name', 'Tom')
print(r.get('name')) # Tom
# 设置过期时间(秒)
r.setex('token', 60, 'abc123') # 60 秒后自动删除
# 自增操作
r.set('counter', 0)
r.incr('counter')
r.incr('counter')
r.incr('counter')
print(r.get('counter')) # 3
5.2 哈希操作
Hash 是 Redis 中最常用的结构之一,特别适合存储对象:
python
# 存储用户信息
r.hset('user:1001', mapping={
'name': 'Tom',
'age': '25',
'city': 'Beijing'
})
# 获取单个字段
print(r.hget('user:1001', 'name')) # Tom
# 获取所有字段
print(r.hgetall('user:1001'))
# {'name': 'Tom', 'age': '25', 'city': 'Beijing'}
5.3 列表操作
python
# 从右侧推入
r.rpush('tasks', 'task1', 'task2', 'task3')
# 获取列表长度
print(r.llen('tasks')) # 3
# 获取指定范围的元素
print(r.lrange('tasks', 0, -1)) # ['task1', 'task2', 'task3']
# 从左侧弹出
print(r.lpop('tasks')) # task1
5.4 集合操作
python
# 添加元素
r.sadd('tags:python', 'web', 'data', 'ai')
r.sadd('tags:java', 'web', 'enterprise', 'android')
# 集合交集(共同标签)
print(r.sinter('tags:python', 'tags:java')) # {'web'}
# 集合并集
print(r.sunion('tags:python', 'tags:java'))
# {'web', 'data', 'ai', 'enterprise', 'android'}
5.5 Pipeline:批量操作的利器
当你需要一次性执行多条命令时,Pipeline 能显著减少网络往返次数:
python
# 不用 Pipeline:3 次网络往返
r.set('a', 1)
r.set('b', 2)
r.set('c', 3)
# 使用 Pipeline:1 次网络往返
pipe = r.pipeline()
pipe.set('a', 1)
pipe.set('b', 2)
pipe.set('c', 3)
results = pipe.execute()
print(results) # [True, True, True]
Pipeline 的原理很简单:它把多条命令打包在一起,一次性发送给 Redis,然后一次性接收所有响应。命令数量越多,Pipeline 的优势越明显。
5.6 Pub/Sub:发布订阅
python
# 创建一个独立的连接用于订阅
pubsub = r.pubsub()
# 订阅频道
pubsub.subscribe('notifications')
# 在另一个进程/线程中发布消息
# r.publish('notifications', 'Hello, everyone!')
# 监听消息
for message in pubsub.listen():
if message['type'] == 'message':
print(f"收到消息: {message['data']}")
六、深入理解:redis-py 如何自动启用 hiredis?
这是很多开发者好奇的地方------redis-py 是怎么"感知"到 hiredis 的存在的?
原理其实不复杂。redis-py 在初始化时会做一次检测:
- 尝试
import hiredis - 如果导入成功,且版本 >= 1.0,就使用 hiredis 的 C 语言解析器
- 如果导入失败,就退回到纯 Python 解析器
这个过程对用户完全透明,你不需要写任何额外代码。
redis-py 的官方文档是这样说的:
For faster performance, install redis with hiredis support, this provides a compiled response parser, and for most cases requires zero code changes. By default, if hiredis >= 1.0 is available, redis-py will attempt to use it for response parsing.
翻译过来就是:装上 hiredis,大多数情况下零代码改动,redis-py 自动启用它。
那什么时候需要手动控制?
极少数情况下,你可能想强制使用纯 Python 解析器(比如调试协议问题)。这时候可以在创建连接时显式指定:
python
import redis
# 强制使用纯 Python 解析器(不推荐在生产环境使用)
r = redis.Redis(host='localhost', port=6379, db=0)
但在实际项目中,几乎没有理由拒绝 hiredis------它是一个免费的性能提升,没有副作用。
七、版本兼容性速查
在使用之前,确认一下版本兼容性,避免踩坑:
redis-py 版本与 Python 版本
| redis-py 版本 | Python 要求 |
|---|---|
| 5.0 | Python 3.7(最后支持) |
| 5.1 ~ 6.1 | Python 3.8+ |
| 6.2+ | Python 3.9+ |
redis-py 版本与 Redis 服务端版本
| redis-py 版本 | 支持的 Redis 版本 |
|---|---|
| 3.5.3 | <= 6.2 |
| >= 4.5.0 | 5.0 ~ 7.0 |
| >= 5.0.0 | 5.0 ~ 7.4 |
| >= 6.0.0 | 7.2 ~ 当前 |
hiredis 版本要求
redis-py 要求 hiredis >= 1.0 ,低于此版本不会被自动启用。当前 hiredis 的稳定版是 1.x 系列,直接 pip install hiredis 装到的就是满足要求的版本。
八、常见问题与注意事项
Q1:装了 hiredis 之后,代码需要改吗?
不需要。 这是 redis-py 设计的初衷------hiredis 是一个透明的加速层,对上层 API 没有任何影响。
Q2:hiredis 装不上怎么办?
hiredis 是一个 C 扩展包,安装时需要编译。如果你在 Windows 上遇到编译错误:
bash
# 确保安装了 Visual C++ Build Tools
# 或者使用预编译的 wheel
pip install hiredis --only-binary=:all:
在 Linux/macOS 上一般不会有问题,系统自带的 GCC/Clang 就能编译。
Q3:redis-py 的 RESP3 协议支持是什么?
从 redis-py 5.0 开始支持 RESP3 协议(Redis 6.0 引入的新协议)。RESP3 相比 RESP2 支持更多数据类型(如布尔值、双精度浮点数、Map 等)。
redis-py 8.0 之后默认使用 RESP3 传输,但为了兼容性,响应格式仍然保持 RESP2 的风格。如果你是新项目,可以显式启用:
python
r = redis.Redis(host='localhost', port=6379, db=0, legacy_responses=False)
Q4:连接池的最大连接数怎么设置?
一般的经验公式:
max_connections = 并发线程数 + 预留余量
比如你有 10 个工作线程,设置 15~20 就够了。设太大会浪费 Redis 端的连接资源。
九、总结
回到文章开头的问题:redis-py 和 hiredis 到底是什么关系?
用一句话概括:
redis-py 是 Python 操作 Redis 的"主力",hiredis 是给它加装的"涡轮增压"。
几个核心要点:
- redis-py 是完整的 Python Redis 客户端,能独立使用,覆盖所有 Redis 命令
- hiredis 是 C 语言实现的高效协议解析器,不直接给 Python 开发者用,而是作为底层引擎
- 两者结合使用时,redis-py 负责上层 API,hiredis 负责底层解析加速
- 安装方式:
pip install "redis[hiredis]",零代码改动即可获得性能提升 - hiredis 只加速响应解析环节,如果瓶颈在网络或 Redis 本身,效果有限
最佳实践建议
| 场景 | 建议 |
|---|---|
| 学习 / 原型开发 | 只装 redis-py 就够了 |
| 生产环境 / 高并发 | 强烈推荐 redis-py + hiredis |
| 需要 RESP3 特性 | redis-py 5.0+,推荐搭配 hiredis |
| Windows 开发环境 | 优先用 --only-binary 安装 hiredis |
十、参考文档
- redis-py 官方仓库:https://github.com/redis/redis-py
- redis-py 官方文档:https://redis.readthedocs.io/en/stable/
- hiredis 官方仓库:https://github.com/redis/hiredis
- Redis 官方命令文档:https://redis.io/commands
- RESP3 协议规范:https://github.com/antirez/RESP3/blob/master/spec.md
- Redis University 免费课程:https://redis.io/learn/university
写在最后:技术选型这件事,不是"越新越好"或"越快越好",而是"适合的才是最好的"。redis-py + hiredis 的组合,本质上就是在"开发便利性"和"运行性能"之间找到了一个很好的平衡点。希望这篇文章能帮你把这个知识点串起来,下次遇到 Redis 性能优化的时候,多一个可选方案。