我来详细介绍如何使用Python操作Redis单节点。以下是完整的操作指南:
1. 安装Redis和Python客户端
# 安装Redis(Linux/Mac)
# Ubuntu/Debian
sudo apt-get install redis-server
# Mac
brew install redis
# 启动Redis
redis-server
# 安装Python Redis客户端
pip install redis
2. 基本连接和操作
import redis
import json
from datetime import timedelta
# 连接到Redis单节点
redis_client = redis.Redis(
host='localhost', # Redis服务器地址
port=6379, # 默认端口
db=0, # 数据库编号(0-15)
password=None, # 密码(如果有)
decode_responses=True, # 自动解码返回字符串
socket_connect_timeout=5 # 连接超时时间
)
# 或者使用连接池(推荐用于生产环境)
pool = redis.ConnectionPool(
host='localhost',
port=6379,
db=0,
max_connections=10 # 最大连接数
)
redis_client = redis.Redis(connection_pool=pool)
3. 基本数据操作
String(字符串)类型
# 设置键值对
redis_client.set('name', '张三')
redis_client.setex('token', 3600, 'abc123') # 设置过期时间(秒)
redis_client.psetex('temp_key', 5000, 'temp_value') # 毫秒过期
# 获取值
name = redis_client.get('name')
print(name) # 输出: 张三
# 批量操作
redis_client.mset({'key1': 'value1', 'key2': 'value2'})
values = redis_client.mget('key1', 'key2')
# 数字操作
redis_client.set('counter', 0)
redis_client.incr('counter') # +1
redis_client.incrby('counter', 5) # +5
redis_client.decr('counter') # -1
Hash(哈希)类型
# 设置哈希字段
redis_client.hset('user:1001', 'name', '李四')
redis_client.hset('user:1001', 'age', 25)
redis_client.hset('user:1001', 'city', '北京')
# 批量设置
redis_client.hmset('user:1002', {
'name': '王五',
'age': 30,
'email': 'wangwu@example.com'
})
# 获取字段
name = redis_client.hget('user:1001', 'name')
all_fields = redis_client.hgetall('user:1001')
# 删除字段
redis_client.hdel('user:1001', 'city')
# 获取所有字段名
fields = redis_client.hkeys('user:1001')
List(列表)类型
# 从左侧插入
redis_client.lpush('tasks', 'task1', 'task2', 'task3')
# 从右侧插入
redis_client.rpush('tasks', 'task4')
# 获取范围
tasks = redis_client.lrange('tasks', 0, -1) # 获取所有
first_two = redis_client.lrange('tasks', 0, 1)
# 弹出元素
left_task = redis_client.lpop('tasks')
right_task = redis_client.rpop('tasks')
# 获取列表长度
length = redis_client.llen('tasks')
Set(集合)类型
# 添加元素
redis_client.sadd('tags', 'python', 'redis', 'database')
redis_client.sadd('tags', 'python') # 重复元素不会添加
# 获取所有成员
all_tags = redis_client.smembers('tags')
# 检查成员是否存在
has_redis = redis_client.sismember('tags', 'redis')
# 集合运算
redis_client.sadd('set1', 'a', 'b', 'c')
redis_client.sadd('set2', 'b', 'c', 'd')
# 交集
intersection = redis_client.sinter('set1', 'set2')
# 并集
union = redis_client.sunion('set1', 'set2')
# 差集
difference = redis_client.sdiff('set1', 'set2')
Sorted Set(有序集合)
# 添加带分数的成员
redis_client.zadd('leaderboard', {
'player1': 100,
'player2': 85,
'player3': 95
})
# 更新分数
redis_client.zincrby('leaderboard', 10, 'player1')
# 获取排名
rank = redis_client.zrevrank('leaderboard', 'player1') # 从高到低排名
score = redis_client.zscore('leaderboard', 'player1')
# 获取前N名
top_players = redis_client.zrevrange('leaderboard', 0, 2, withscores=True)
# 按分数范围获取
players = redis_client.zrangebyscore('leaderboard', 90, 100)
4. 高级功能
过期时间管理
# 设置过期时间
redis_client.set('session:user1', 'data')
redis_client.expire('session:user1', 1800) # 30分钟后过期
redis_client.expireat('session:user1', 1672531200) # 指定时间戳过期
# 获取剩余时间
ttl = redis_client.ttl('session:user1') # 返回剩余秒数
pttl = redis_client.pttl('session:user1') # 返回剩余毫秒数
# 持久化(移除过期时间)
redis_client.persist('session:user1')
管道操作(批量执行)
# 使用管道提高性能
pipe = redis_client.pipeline()
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.incr('counter')
pipe.get('key1')
# 执行所有命令
results = pipe.execute()
print(results) # [True, True, 1, b'value1']
事务操作
# 使用事务确保原子性
try:
pipe = redis_client.pipeline(transaction=True)
pipe.watch('balance') # 监视键
balance = int(redis_client.get('balance') or 0)
if balance >= 100:
pipe.multi() # 开始事务
pipe.decrby('balance', 100)
pipe.incrby('savings', 100)
pipe.execute() # 提交事务
print("转账成功")
else:
print("余额不足")
pipe.unwatch()
except redis.WatchError:
print("事务执行期间数据被修改,事务已取消")
发布/订阅模式
import threading
# 订阅者
def subscriber():
pubsub = redis_client.pubsub()
pubsub.subscribe('news')
for message in pubsub.listen():
if message['type'] == 'message':
print(f"收到消息: {message['data']}")
# 发布者
def publisher():
for i in range(5):
redis_client.publish('news', f'消息 {i}')
time.sleep(1)
# 启动线程
threading.Thread(target=subscriber).start()
threading.Thread(target=publisher).start()
5. 实用工具函数
class RedisHelper:
def __init__(self, host='localhost', port=6379, db=0):
self.redis_client = redis.Redis(
host=host,
port=port,
db=db,
decode_responses=True
)
# 缓存装饰器
def cache(self, timeout=300):
def decorator(func):
def wrapper(*args, **kwargs):
# 生成缓存键
cache_key = f"{func.__name__}:{str(args)}:{str(kwargs)}"
# 尝试从缓存获取
cached_result = self.redis_client.get(cache_key)
if cached_result is not None:
return json.loads(cached_result)
# 执行函数
result = func(*args, **kwargs)
# 缓存结果
self.redis_client.setex(
cache_key,
timeout,
json.dumps(result)
)
return result
return wrapper
return decorator
# 分布式锁
def acquire_lock(self, lock_name, acquire_timeout=10, lock_timeout=10):
"""获取分布式锁"""
identifier = str(uuid.uuid4())
lock_key = f"lock:{lock_name}"
lock_timeout = int(lock_timeout)
end = time.time() + acquire_timeout
while time.time() < end:
if self.redis_client.setnx(lock_key, identifier):
self.redis_client.expire(lock_key, lock_timeout)
return identifier
if self.redis_client.ttl(lock_key) < 0:
self.redis_client.expire(lock_key, lock_timeout)
time.sleep(0.001)
return False
def release_lock(self, lock_name, identifier):
"""释放分布式锁"""
lock_key = f"lock:{lock_name}"
with self.redis_client.pipeline() as pipe:
while True:
try:
pipe.watch(lock_key)
if pipe.get(lock_key) == identifier:
pipe.multi()
pipe.delete(lock_key)
pipe.execute()
return True
pipe.unwatch()
break
except redis.WatchError:
pass
return False
# 限流器
def rate_limit(self, key, limit, period):
"""限流器"""
current = self.redis_client.incr(key)
if current == 1:
self.redis_client.expire(key, period)
return current <= limit
6. 完整示例:用户会话管理
import hashlib
import time
class SessionManager:
def __init__(self, redis_client):
self.redis = redis_client
self.session_prefix = "session:"
self.session_timeout = 1800 # 30分钟
def create_session(self, user_id, user_data):
"""创建会话"""
session_id = hashlib.sha256(
f"{user_id}{time.time()}".encode()
).hexdigest()
session_key = f"{self.session_prefix}{session_id}"
# 存储会话数据
session_data = {
'user_id': user_id,
'created_at': time.time(),
'data': user_data
}
self.redis.hmset(session_key, session_data)
self.redis.expire(session_key, self.session_timeout)
return session_id
def get_session(self, session_id):
"""获取会话"""
session_key = f"{self.session_prefix}{session_id}"
if not self.redis.exists(session_key):
return None
# 更新过期时间
self.redis.expire(session_key, self.session_timeout)
return self.redis.hgetall(session_key)
def destroy_session(self, session_id):
"""销毁会话"""
session_key = f"{self.session_prefix}{session_id}"
self.redis.delete(session_key)
def update_session_data(self, session_id, data):
"""更新会话数据"""
session_key = f"{self.session_prefix}{session_id}"
if self.redis.exists(session_key):
for key, value in data.items():
self.redis.hset(session_key, key, value)
return True
return False
7. 配置和最佳实践
# 配置文件示例
REDIS_CONFIG = {
'host': 'localhost',
'port': 6379,
'db': 0,
'password': None,
'socket_timeout': 5,
'socket_connect_timeout': 5,
'retry_on_timeout': True,
'max_connections': 20,
}
# 连接池管理
class RedisManager:
_pool = None
@classmethod
def get_client(cls):
if cls._pool is None:
cls._pool = redis.ConnectionPool(**REDIS_CONFIG)
return redis.Redis(
connection_pool=cls._pool,
decode_responses=True
)
# 使用
redis_client = RedisManager.get_client()
8. 错误处理
from redis.exceptions import (
ConnectionError,
TimeoutError,
RedisError
)
def safe_redis_operation():
try:
# Redis操作
result = redis_client.get('key')
return result
except ConnectionError:
print("无法连接到Redis服务器")
# 重试逻辑或使用备用方案
except TimeoutError:
print("Redis操作超时")
except RedisError as e:
print(f"Redis错误: {e}")
finally:
# 清理资源
pass
注意事项
- 连接管理:使用连接池避免频繁创建连接
- 序列化:复杂对象需要序列化存储(如使用JSON)
- 内存管理:定期清理过期数据,监控内存使用
- 错误处理:所有操作都应包含异常处理
- 性能优化:使用管道、批量操作提高性能
- 键命名规范:使用有意义的键名,如
user:1001:profile
这个指南涵盖了Redis单节点操作的主要方面,你可以根据具体需求选择使用。