Redis 键值对操作详解:Python 实现指南

发布于:2025-07-30 ⋅ 阅读:(21) ⋅ 点赞:(0)

一、环境准备

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 命令
执行方式 同步删除(阻塞操作) 异步删除(非阻塞操作)
适用场景 小型键值对 大型键值对(哈希、列表等)
性能影响 可能阻塞服务器 后台执行,不影响主线程
返回值 删除的键数量 删除的键数量
内存回收 立即回收 延迟回收
Python方法 .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() - start

print(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, TimeoutError
import time

def 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 False

safe_operation()

4. 性能优化技巧

  1. 批量操作:使用 MSET 替代多个 SET,使用管道处理批量命令
  2. 键名设计:使用可读的命名空间(如 user:1000:profile
  3. 过期时间:为临时数据设置 TTL,避免手动删除
  4. 异步删除:大型数据删除始终使用 UNLINK
  5. 连接复用:避免频繁创建/关闭连接

六、总结与选择建议

操作选择矩阵

场景 推荐操作 替代方案
添加小数据 SET HSET(对象)
添加大数据 HSET/MSET 分批次添加
添加临时数据 SETEX SET + EXPIRE
删除小数据 DELETE UNLINK
删除大数据 UNLINK
批量操作 管道 + MSET/UNLINK 单独命令

核心要点总结

  1. 添加操作

    • 使用 set() 添加单个键值对
    • 使用 mset() 批量添加多个键值对
    • 使用 setex() 添加带过期时间的键值对
  2. 删除操作

    • 优先使用 unlink() 进行删除(尤其大型数据)
    • 仅在需要立即释放内存时使用 delete()
    • 批量删除时结合管道提高效率
  3. 性能关键

    • UNLINK 比 DELETE 快数百倍(大型数据)
    • 管道操作可减少网络往返时间
    • 合理设置过期时间减少手动删除
  4. 最佳实践

    • 生产环境默认使用 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 的核心区别,并在不同场景下选择最优的操作策略。


网站公告

今日签到

点亮在社区的每一天
去签到