用 Redis 给 AI Agent 手写一套会话运行时,简单、粗暴、高效

Flashduty AI SRE 技术揭秘第 1 篇:用 Redis 锁、列表和 Pub/Sub 构建分布式 Agent 会话运行时,实现消息顺序处理、故障恢复与空闲资源回收,并说明方案的适用边界。

作者 快猫星云

暖米色手绘插画:管家一次服务一位客人,其他客人拿着号码牌在沙发上安静等待,四周保留大面积留白。

一个会话,一位管家;消息按顺序等待处理。

Flashduty AI SRE( https://www.flashduty.com ) 是一个专注 SRE 领域、帮你做故障根因分析、日常运维工作的 AI Agent 产品,注册即可免费试用,这是系列文章《Flashduty AI SRE 技术揭秘》第 1 篇,本系列会持续分享我们在 agent 工程上的真实设计、踩过的坑和做过的取舍,为了把它做到生产级水准,可以唠的点还是蛮多的。

一切的起源,都是因为我们把 AI Agent 搞成了分布式,因为我们希望 AI Agent 可以 7x24 运行,同时服务组织内的所有用户,还希望它把任务均匀打散,希望它是一个企业级的解决方案,这相比在本机运行一个 Codex、Cursor,带来了很多额外挑战。

本篇是系列第 1 篇,讲解一下消息处理机制:对于每个 AI Agent 会话,要保证同一次对话里的消息严格按顺序处理、服务器重启不丢消息不丢工作、闲着的会话不吃资源。我们折腾了挺久,最终方案可以概括为:

给每个会话配一个"专职管家",用 Redis 里一把 30 秒自动过期的 Lock,保证同一时刻整个系统里只有一个管家在服务这个会话。

剩下所有设计——消息怎么排队、服务器挂了怎么办、为什么不用现成的消息队列——全都据此展开。

问题背景

用户给 agent 发一句话:“帮我看看昨晚的告警是怎么回事。“接下来 agent 可能要跑好几分钟:查监控、翻日志、执行命令、调各种工具。

体会一下这和普通 Web 请求的差别。一个普通接口几十毫秒返回,中间出了错,前端重试一次即可。而 agent 的一轮分析是另一回事:它要调用十几次大模型,烧掉的是真金白银的 token 费用;它执行的命令可能动了真实环境;用户就守在屏幕前,看着它一条一条往外吐进展。这种负载,“中间出点问题"的代价被放大了很多倍——偏偏在这几分钟里,麻烦一定会来(唉,该死的墨菲定律):

  1. 用户会追加消息。“顺便看下数据库的慢查询。“这句话不能打断正在进行的分析——模型正等着上一个工具的结果,硬切进去会把工具调用切得七零八落,上下文直接报废;也不能丢——丢了,用户就是眼睁睁看着自己打的字被吞掉。它得乖乖排队,等这一轮跑完再处理。
  2. 服务器会重启。我们每次发布新版本,机器要滚动下线。设想一下:一次分析跑了四分钟,还差一分钟出结论,承载它的进程收到了下线信号。如果没人接手,用户面前就是一个永远转圈的加载动画——而那四分钟烧掉的 token,抱歉,白花了。
  3. 我们有很多台服务器(多个 pod)。用户的下一条消息可能被负载均衡送到任何一台机器上,但同一个会话的活,必须只有一个人在干。设想一下没人协调会发生什么:两台机器同时认领了同一个会话,同一轮分析跑两遍,账单翻倍;同一个工单被创建两次,同一个重启命令被执行两次;两份输出交错写进同一份会话历史,agent 从此在自己没说过的话里找上下文,开始一本正经地胡言乱语。

这些问题,都是很典型的分布式系统要处理的问题,有人说 AI Agent 本质上仍然是一个工程问题,深以为然。

三个设计决定

一把锁,保证只有一个管家

每个会话对应一个"管家”(我们内部叫 actor,其实就是一段专门服务这个会话的代码)。管家上岗前,要先去 Redis 抢一把锁:

  • 锁的写法是"不存在才能创建,30 秒后自动过期”(Redis 的 SET NX EX)。抢到的那个进程就是唯一合法管家,抢不到的立刻退出。
  • 上岗后每 10 秒续一次约,证明自己还活着。
  • 会话闲置超过 5 分钟,管家主动交锁下班,不占着位置。

如果管家所在的进程崩了呢?锁最多 30 秒后自动过期,别的进程抢锁上岗,会话自动复活。不需要人工介入,也不需要复杂的选主协议——锁自己会过期,就是最可靠的"死亡证明”。

发消息的人只投递,不等待

所有想给会话递话的入口——网页端的消息接口、子 agent 干完活的汇报、自动化任务的触发——都只干两件事:把消息追加到这个会话在 Redis 里的队列尾部,然后喊一嗓子"有活了”(发一条 Redis Pub/Sub 通知)。喊完就走,绝不阻塞。

管家那边循环做三件事:把队列里的消息一条条取出来处理;处理完从队列里删掉;队列空了就睡觉,等下一声"有活了”。

这个"投递与处理分离"的结构带来一个好处:生产者的数量、速度和位置,全都和管家无关。消息可以从任何一台机器、任何进程塞进来,顺序由 Redis 队列保证,处理永远只有一个出口。

闲着的管家,不许占资源

这是最容易被忽略、但对成本影响最大的一条。

一个 agent 平台的特点是:绝大部分会话在绝大部分时间里都是闲的。用户问完一个问题就走了,会话挂在那儿,可能半小时后才有下一句。如果每个空闲管家都占着一条 Redis 连接傻等(用阻塞式的读取),那 Redis 的连接数就会随着空闲会话数线性膨胀——一万个挂着的会话就是一万条连接,光握手和维护就是一笔开销。

我们的做法是:管家把队列掏空之后,不占任何 Redis 连接,就睡在自己进程的内存里,等本机或其他机器的"有活了"通知来叫醒它。怕通知万一丢了,再加一道保险:每 5 秒睁眼瞟一眼队列,有活就干,没活继续睡。5 秒的延迟对"几分钟后才回来的用户"完全无感,但 Redis 连接数从此和空闲会话数彻底脱钩——它只跟"此刻真正在干活的会话数"挂钩。

暖色手绘运行时示意图:网页用户、子任务和定时任务向同一队列投递消息,一位管家顺序处理;下方展示管家的空闲休眠状态,右侧分别是持久账本和临时广播。

多个入口投递,一位管家顺序处理;下方是同一管家的空闲状态。账本保留事件,广播负责即时通知。

管家猝死了,办到一半的事怎么办

上面的流程有一个明显的窟窿:管家从队列里取出一条消息,正在处理,进程崩了。这条消息已经从队列里拿走了——它去哪了?

解决办法是记账分两步。管家取消息时,不是直接取走,而是把消息从"待办队列"搬到"加工台"(Redis 里另一个列表);只有处理成功了,才把加工台上的这条划掉。

新管家上岗的第一件事,就是检查加工台:上一任有没有留下没办完的事?有就原样搬回待办队列的头部,重新排队。消息不会丢,顺序也不会乱——代价是同一条消息可能被处理两次,所以下游的每一步处理都设计成"重复执行无害"的。

这个模式其实非常老,老到每个消息队列教程里都有。但在 agent 场景里,值得单独唠唠:一条消息背后可能是一次已经跑了几分钟、烧了不少 token 的分析。丢一条消息的代价不再是"少发一封邮件",而是"用户眼睁睁看着分析中断",token 白烧了。

我们故意没做的事

讲完了做了什么,再讲讲没做什么。

没用 Redis Streams,也没上 Kafka。 几乎所有"正经"的分布式队列方案我们都评估过,最后选了最土的一种:Redis 列表 + Pub/Sub。理由是:会话事件的真相存在 MySQL 里,每一条消息、每一次工具调用、每一个模型回复都落库;Redis 里的东西从设计第一天起就被当成"可以随时重建的缓存"。队列丢了?消息在库里。直播通知丢了?客户端重连后从库里按游标补齐。既然有数据库兜底,就没有理由再引入一套需要自己运维的流式存储——那只会让"真相"变成两份,然后你一辈子都在处理两份真相不一致的问题。

没做会话的自动迁移和负载均衡。 一个会话固定在哪个管家手里,取决于谁抢到锁,没有"把忙机器的会话挪到闲机器"这类机制。agent 会话的真实负载大头在模型 API 的等待上,不在我们的进程上,没必要为进程负载做迁移。

这两条不做,就简单多了:整个运行时只有 Redis 和 MySQL 两个依赖,任何一个熟悉普通后端服务的工程师都能在一个下午看懂全部机制。

这套方案的边界、适用前提

这套设计有明确的适用前提:它假设单个会话的处理是严格串行的,且单会话的吞吐上限就是一个管家。如果你的场景是单会话每秒要处理几百条消息,这个模型第一天就会撞墙。

但 agent 场景恰好相反:会话数量巨大,单个会话的消息稀稀拉拉,每条消息的处理时间以分钟计。给这样的负载配"一个会话一个串行管家",就像给酒店客人配一对一服务——听起来奢侈,实际上管家大部分时间在沙发上睡觉,真正贵的不是管家的数量,而是你让管家们傻等时占用的资源。把"闲着不许占资源"这一条搞定,这套土办法就能用两个最常见的中间件,撑起一个多租户的 agent 平台。

当然,“顺序"只是会话运行时要解决的一半问题。另一半更棘手:用户随时会按"停止”,而停止请求到达的时候,这一轮可能还没开始跑。下一次发布时抢锁和停止的指令赛跑,谁先到?我们为此栽过一个真实的跟头——用户点了停止,agent 却照常跑完了全程,我们内部管那次事故叫"停了个寂寞"。下一篇就讲我们怎么用一块"墓碑"修掉它。


这是 “Flashduty AI SRE( https://www.flashduty.com )技术内幕” 系列的第一篇。我们在做一个专注 SRE 领域、帮你做故障根因分析的 AI Agent 产品,本系列会持续分享我们在 agent 工程上的真实设计、踩过的坑和做过的取舍。

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云