Redis 实战教程
你是不是还在吐槽Web应用查询慢、偶尔Session丢、甚至电商超售超订?今天带大家从「0安装」到「Python高频场景落地」,用轻量高效的方案解决这些问题!
什么是Redis?
Redis(Remote Dictionary Server)是一个开源的内存优先数据结构存储系统,可以同时当缓存、半持久化数据库、轻量消息中间件用。它最大的特点是支持比普通键值多太多的结构化操作,能帮我们用Redis原生命令快速实现复杂逻辑,不用在应用层写一堆代码。
简单列几个生产级常用特点:
- 毫秒级响应:全内存存储,单节点读写可达10万/秒+
- 数据半落地:RDB(定时快照)+ AOF(增量日志)双持久化,兼顾速度和安全
- 主从/哨兵/集群全覆盖:从读写分离到高可用,再到分布式横向扩容
- Lua脚本原子操作:解决超卖、计数一致性的神器
1. 3步快速安装Redis
1.1 推荐方案:Docker一键启动
不管你是Windows、Mac还是Linux,Docker都能避免环境依赖问题:
# 1. 拉取官方稳定版(LTS最新通常选7.x以上)
docker pull redis:7-alpine
# 2. 后台启动,绑定本地6379端口,开启持久化
docker run -d \
--name my-redis-dev \
-p 6379:6379 \
-v redis-data-dev:/data \
redis:7-alpine \
redis-server --appendonly yes
# 3. 测试连接
docker exec -it my-redis-dev redis-cli ping
# 输出PONG就成功了!
1.2 备用:WSL/Ubuntu原生
如果不习惯Docker,用WSL 2 Ubuntu/Debian安装:
sudo apt update && sudo apt install -y redis-server
sudo systemctl enable --now redis-server
redis-cli ping # 测试
2. 高频Redis数据类型速览(附代码)
Redis的核心不是“存键值”,而是用对应的数据结构解决对应问题!下面只列生产中80%场景会用到的类型:
2.1 字符串(String):万金油
存单个值、计数器、临时token都能用:
# 设置带过期时间的token(NX=仅不存在时设,EX=过期秒数)
SET token:user:1000 "abc123xyz" EX 3600 NX
# 获取token
GET token:user:1000
# 原子自增(电商库存、日活统计)
INCR daily:active:users
INCRBY product:stock:2024 5 # 补5件库存
2.2 哈希(Hash):存对象更省内存
代替“user:1000:name=xx”这种散列的字符串键,节省约30-50%的内存:
# 设置用户信息
HSET user:profile:1000 name "道满Python" role "博主" age 28
# 批量获取指定字段
HMGET user:profile:1000 name role
# 只获取某个字段
HGET user:profile:1000 age
2.3 列表(List):轻量队列/栈
用LPUSH/RPUSH+BRPOP/BLPOP实现阻塞式消息队列,完全不用引入RabbitMQ/Kafka这种重量级中间件:
# 模拟生产者:左侧推入待处理订单
LPUSH orders:todo "order:20240501001" "order:20240501002"
# 模拟消费者:右侧阻塞等待订单(0=永久等待)
BRPOP orders:todo 0
2.4 有序集合(Sorted Set):自动排行榜
按分数(比如点赞数、分数、时间戳)自动排序,无需应用层操作:
# 发布文章并设置初始点赞数
ZADD article:likes 0 "article:20240501001"
# 点赞+1(ZINCRBY自动更新排序)
ZINCRBY article:likes 1 "article:20240501001"
# 获取点赞数前3的文章(带分数,倒序)
ZREVRANGE article:likes 0 2 WITHSCORES
3. Python与Redis无缝集成
生产环境推荐用官方维护的 redis 库,支持同步/异步:
3.1 安装与基础连接
# 安装同步/异步通用库
pip install redis redis[hiredis] # hiredis是C加速解析器,性能翻倍
import redis
# 同步基础连接(自动解码响应,避免bytes转str)
r = redis.Redis(
host="localhost",
port=6379,
db=0,
decode_responses=True,
socket_timeout=5 # 超时避免卡死
)
print(r.ping()) # 测试
3.2 高频Python场景1:接口缓存
写个装饰器就能给任意同步/异步接口加Redis缓存,避免频繁查库:
import json
from functools import wraps
# 同步装饰器
def sync_cache(expire=300):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 生成唯一缓存键(要考虑参数顺序)
key = f"cache:{func.__name__}:{hash(repr(args)+repr(sorted(kwargs.items())))}"
cached = r.get(key)
if cached:
return json.loads(cached)
# 查库并缓存
res = func(*args, **kwargs)
r.setex(key, expire, json.dumps(res, ensure_ascii=False))
return res
return wrapper
return decorator
# 测试装饰器
@sync_cache(expire=600)
def get_user_profile(user_id: int):
print("=== 模拟数据库查询 ===")
return {"id": user_id, "name": "道满Python", "role": "博主"}
print(get_user_profile(1000)) # 第一次查库
print(get_user_profile(1000)) # 第二次走缓存
3.3 高频Python场景2:超卖原子锁
用Lua脚本+SET NX EX解决电商秒杀、预约挂号的超卖问题,保证原子性:
import uuid
# Lua脚本:检查库存>0 → 扣减库存 → 返回扣减结果
LUA_DEDUCT_STOCK = """
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock and stock >= tonumber(ARGV[1]) then
redis.call('DECRBY', KEYS[1], tonumber(ARGV[1]))
return 1 -- 成功
end
return 0 -- 失败
"""
def deduct_stock(product_id: int, count: int = 1):
key = f"product:stock:{product_id}"
# 加载脚本(缓存后SHA执行更快)
sha = r.script_load(LUA_DEDUCT_STOCK)
try:
res = r.evalsha(sha, 1, key, count)
return res == 1
except Exception as e:
# 如果脚本过期(比如重启Redis),重新加载
print(f"脚本过期,重新加载:{e}")
return deduct_stock(product_id, count)
# 测试
r.set("product:stock:2024", 3) # 初始3件库存
for _ in range(5): # 5个请求
print(f"秒杀{'成功' if deduct_stock(2024) else '失败'}")
4. Redis小技巧避坑
4.1 键命名规范
团队统一规范避免混乱,推荐用 业务:模块:资源ID 的冒号分层:
✅ session:user:1000
✅ cache:article:list:page1
✅ product:stock:2024
❌ a123456(无业务含义)
❌ User_Profile-1000(符号混用)
4.2 慢查询监控
生产环境用 SLOWLOG GET 10 查最近10条超过指定时间的命令,默认超过10000微秒(10ms)记录:
# 临时设置慢查询阈值为5ms(生产建议永久改配置文件)
CONFIG SET slowlog-log-slower-than 5000
总结
Redis是一款轻量但功能爆炸的工具,只要选对数据结构,就能用最少的代码解决最棘手的性能问题。今天我们学了:
- Docker一键启动开发环境
- 4种高频数据结构的用法
- Python加接口缓存、超卖原子锁的完整代码
- 生产避坑的小技巧
如果想深入学习,可以看后面的「哨兵模式/集群模式」和「内存优化」内容!