用 Redis 管理对话会话:状态存储与缓存实践
唐唐老师123 阅读
做一个聊天应用,对话历史不能每次请求都从数据库全量查出来(太慢),也不能全放内存(进程重启就丢)。Redis 是我最后选的方案:快、带过期、天然适合这种场景。
存储结构:
每个会话一条记录,用 List 存消息历史:
Bash
# key: session:{id}:history
RPUSH session:abc:history '{"role":"user","content":"你好"}'
RPUSH session:abc:history '{"role":"assistant","content":"你好!"}'
# 设置过期:30 分钟无交互自动清理
EXPIRE session:abc:history 1800
滑动过期:每次用户发消息时重置过期时间,实现"30 分钟不活跃自动回收会话"。这个对资源管理很重要——不活跃的会话长期占着内存,会越积越多。
上下文组装:取最近 N 条消息拼成请求:
Bash
LRANGE session:abc:history -20 -1
只取最后 20 条,避免历史无限增长撑爆 context。
坑一:消息体积。RAG 场景下,每条消息可能带检索上下文(几千字)。存 Redis 没问题,但取 20 条可能几万 token。我在存储前对上下文做压缩(只存摘要 + 关键片段)。
坑二:并发写入。同一个会话两个请求同时追加消息,用 RPUSH 是原子的没问题,但如果要做"读取-修改-写回"(比如压缩历史),要加锁或用 Lua 脚本,防止竞态。
坑三:Redis 挂了。Redis 是缓存不是数据库,丢了会话可以重建(提示用户重开对话),但不能把关键业务状态只放 Redis。会话的最终状态要有持久化兜底。
坑四:序列化格式。Redis 存 JSON 字符串要注意转义,消息里可能有特殊字符。用 json.dumps/loads 处理,别手动拼字符串。
进阶:多机部署。如果是多实例部署,Redis 天然共享会话状态,不用做本地会话同步。这也是选 Redis 而不是本地内存的原因。
总结:Redis 存会话的核心是"List 存消息 + 滑动过期 + 只取最近 N 条",简单可靠。
评论0
还没有评论,来抢沙发~