Redis 键值对操作详解:Python 实现指南_python redis hset mapping 批量设置字段
一、环境准备
1. 安装依赖库
pip install redis
2. 连接 Redis 数据库
import redis# 创建 Redis 客户端连接r = redis.Redis( host=\'localhost\', # Redis 服务器地址 port=6379, # Redis 端口 db=0, # 数据库编号(0~15) password=None, # 密码(若无密码则为 None) decode_responses=True # 自动解码返回值为字符串)# 测试连接try: r.ping() print(\"成功连接到 Redis 服务器\")except redis.ConnectionError: print(\"无法连接 Redis 服务器\")
二、添加键值对操作
1. 添加单个键值对
# 添加/覆盖键值对result = r.set(\"username\", \"john_doe\")print(f\"添加结果: {result}\") # 输出: True# 添加带条件的键值对(仅当键不存在时)result = r.set(\"email\", \"john@example.com\", nx=True)print(f\"条件添加结果: {result}\") # 键不存在时返回 True,存在时返回 None
2. 批量添加键值对
# 批量添加多个键值对data = { \"user:1001:name\": \"Alice\", \"user:1001:age\": \"28\", \"user:1001:city\": \"London\"}result = r.mset(data)print(f\"批量添加结果: {result}\") # 输出: True
3. 添加带过期时间的键值对
# 设置键值对并在60秒后自动过期result = r.setex(\"session_token\", 60, \"a1b2c3d4e5\")print(f\"带过期时间的添加结果: {result}\") # 输出: True# 检查剩余生存时间ttl = r.ttl(\"session_token\")print(f\"剩余生存时间: {ttl}秒\") # 输出: 60
4. 添加大型键值对
# 创建大型数据集large_data = {f\"item_{i}\": f\"value_{i}\" for i in range(10000)}# 添加大型哈希表result = r.hset(\"large:hash\", mapping=large_data)print(f\"添加大型哈希表结果: {result}\") # 输出: 添加的字段数量
三、删除键值对操作
1. DELETE 命令(同步删除)
# 删除单个键result = r.delete(\"username\")print(f\"删除单个键结果: {result}\") # 输出: 1 (成功删除)# 删除多个键keys_to_delete = [\"user:1001:name\", \"user:1001:age\", \"non_existent_key\"]result = r.delete(*keys_to_delete)print(f\"删除多个键结果: {result}\") # 输出: 2 (实际删除的键数)
2. UNLINK 命令(异步删除)
# 异步删除单个大键result = r.unlink(\"large:hash\")print(f\"UNLINK 单个键结果: {result}\") # 输出: 1# 异步删除多个键keys_to_unlink = [\"session_token\", \"temp:data\", \"cache:item\"]result = r.unlink(*keys_to_unlink)print(f\"UNLINK 多个键结果: {result}\") # 输出: 实际删除的键数
3. DELETE vs UNLINK 对比
.delete()
.unlink()
4. 删除性能对比测试
import time# 创建大型测试数据large_hash = {f\"key_{i}\": f\"value_{i}\" for i in range(50000)}r.hset(\"test:large:hash\", mapping=large_hash)# 测试 DELETE 性能start = time.time()r.delete(\"test:large:hash\")delete_duration = time.time() - start# 重新创建数据r.hset(\"test:large:hash\", mapping=large_hash)# 测试 UNLINK 性能start = time.time()r.unlink(\"test:large:hash\")unlink_duration = time.time() - startprint(f\"DELETE 耗时: {delete_duration:.4f}秒\")print(f\"UNLINK 耗时: {unlink_duration:.4f}秒\")print(f\"性能差异: DELETE 比 UNLINK 慢 {delete_duration/unlink_duration:.1f}倍\")
四、高级操作技巧
1. 管道操作(批量执行)
# 使用管道批量添加和删除with r.pipeline() as pipe: # 批量添加 pipe.set(\"counter\", 0) pipe.incrby(\"counter\", 100) pipe.set(\"status\", \"active\") # 批量删除 pipe.delete(\"temp:data1\", \"temp:data2\") pipe.unlink(\"large:cache\") # 执行所有命令 results = pipe.execute()print(f\"管道操作结果: {results}\")
2. 哈希表操作
# 添加哈希表r.hset(\"user:1002\", mapping={ \"name\": \"Bob\", \"email\": \"bob@example.com\", \"age\": \"32\"})# 获取哈希表字段name = r.hget(\"user:1002\", \"name\")print(f\"用户名: {name}\")# 删除哈希表字段r.hdel(\"user:1002\", \"age\")# 获取所有字段all_fields = r.hgetall(\"user:1002\")print(f\"用户数据: {all_fields}\")
3. 键存在性检查
# 检查单个键是否存在exists = r.exists(\"username\")print(f\"键存在: {bool(exists)}\") # 输出: True 或 False# 检查多个键是否存在count = r.exists(\"key1\", \"key2\", \"key3\")print(f\"存在的键数量: {count}\")
五、最佳实践与注意事项
1. 键操作选择指南
- 小型字符串键:DELETE 或 UNLINK 均可
- 大型数据结构:始终使用 UNLINK
- 批量删除操作:优先使用 UNLINK + 管道
- 需要立即释放内存:使用 DELETE
- 高并发环境:优先使用 UNLINK
2. 内存管理建议
# 监控内存使用情况info = r.info(\"memory\")print(f\"已用内存: {info[\'used_memory_human\']}\")print(f\"待删除对象: {info[\'lazyfree_pending_objects\']}\")
3. 错误处理与重试
from redis.exceptions import ConnectionError, TimeoutErrorimport timedef safe_operation(): attempts = 0 max_attempts = 3 while attempts < max_attempts: try: # 尝试执行操作 return r.set(\"important:data\", \"critical_value\", ex=30) except (ConnectionError, TimeoutError) as e: attempts += 1 print(f\"操作失败 ({attempts}/{max_attempts}): {str(e)}\") time.sleep(2 ** attempts) # 指数退避 print(\"操作失败,达到最大重试次数\") return Falsesafe_operation()
4. 性能优化技巧
- 批量操作:使用 MSET 替代多个 SET,使用管道处理批量命令
- 键名设计:使用可读的命名空间(如
user:1000:profile
) - 过期时间:为临时数据设置 TTL,避免手动删除
- 异步删除:大型数据删除始终使用 UNLINK
- 连接复用:避免频繁创建/关闭连接
六、总结与选择建议
操作选择矩阵
核心要点总结
-
添加操作:
- 使用
set()
添加单个键值对 - 使用
mset()
批量添加多个键值对 - 使用
setex()
添加带过期时间的键值对
- 使用
-
删除操作:
- 优先使用
unlink()
进行删除(尤其大型数据) - 仅在需要立即释放内存时使用
delete()
- 批量删除时结合管道提高效率
- 优先使用
-
性能关键:
- UNLINK 比 DELETE 快数百倍(大型数据)
- 管道操作可减少网络往返时间
- 合理设置过期时间减少手动删除
-
最佳实践:
- 生产环境默认使用 UNLINK
- 监控 lazyfree_pending_objects 指标
- 使用指数退避策略处理连接错误
# 最终推荐操作模式def redis_best_practice(): # 添加数据 r.set(\"app:status\", \"running\", ex=3600) # 带过期时间 r.mset({\"config:theme\": \"dark\", \"config:lang\": \"en\"}) # 删除数据 r.unlink(\"old:cache:data\") # 大型数据 r.unlink(\"temp:session:1\", \"temp:session:2\") # 批量删除 # 使用管道 with r.pipeline() as pipe: pipe.incr(\"counter:requests\") pipe.expire(\"counter:requests\", 86400) pipe.unlink(\"obsolete:key\") pipe.execute()
通过本指南,您应该能够熟练地在 Python 中实现 Redis 的键值对添加和删除操作,理解 DELETE 和 UNLINK 的核心区别,并在不同场景下选择最优的操作策略。