news 2026/9/30 4:59:44

Redis与AI结合实践:语义缓存、向量检索与Agent状态协调

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis与AI结合实践:语义缓存、向量检索与Agent状态协调

Redis 已正式接入 AI。这几天类似的说法在好几个技术群里来回刷,有人以为官方悄悄发布了一个新大模型,有人觉得这就是个标题党。作为一名常年跟缓存、数据中间件、LLM 应用工程化打交道的开发者,我更愿意把这句话理解成一个明确的信号:Redis 已经从单纯的缓存中间件,变成了 AI 应用里绕不开的数据底座。不管你是做 RAG、做 Agent、做模型推理加速,还是单纯想用 AI 辅助自己写 Redis 代码,Redis 和 AI 的结合都不是“未来趋势”,而是今天就能落地的工程事实。这篇文章我不讲 PPT,也不做产品预告,就把我在实际项目里跑通的几类 Redis + AI 场景,以及踩过的坑,一次性说清楚。

我默认读者分两类:一类是后端工程师,Redis 基础没问题,但对 LLM 应用怎么用 Redis 还比较模糊;另一类是算法/全栈同学,平时写 Python 调模型很溜,但对 Redis 的数据结构、部署、分布式锁这些工程细节不熟。文章里的内容两端都能覆盖,你可以按需跳到对应章节。

1. Redis 与 AI 结合的四条真实路径,别只盯着“官方新品”

很长一段时间里,人们提到 Redis 就两个词:缓存、队列。但 LLM 应用大规模落地之后,Redis 的角色被硬生生拓宽了。我自己归纳下来,当前 Redis 和 AI 的真实交集至少有四条路径,每条路径解决的实际问题都不同。

1.1 语义缓存:给大模型接口加一道成本闸门

先说最直接的一条:大模型接口调用贵、延迟高,而且大量用户问题在语义上高度重复。任何一个 AI 产品上线后,你去看日志,问“怎么退款”“退款流程是什么”“如何申请退款”的用户可能是同一批话术。如果每次都打到模型服务,等待 2 到 5 秒太常见了。这时候如果把问题和答案缓存起来,下次直接用缓存结果,成本能降一个数量级。

但传统 Redis String 缓存只能做精确匹配——问题文本完全一样才会命中。用户话术稍微换个说法就 miss 了。于是“语义缓存”出现:先把用户问题做向量化,把向量存进 Redis,用向量相似度判断“这个问题以前是不是问过”,如果相似度足够高,直接把历史答案返回。这要求 Redis 具备向量检索能力,而这不是什么科幻场景,向量索引和相似度检索已经是 Redis 生态里的成熟能力。

1.2 向量检索:RAG 应用的记忆层

RAG(检索增强生成)的核心是“先检索相关资料,再让模型基于资料回答”。检索的数据存在哪里?常见方案是专门的向量数据库。但如果你是中小团队,或者刚开始做 RAG,并不想为了检索单独维护一套集群,Redis 的向量检索能力就非常划算。它能把业务状态、会话数据、向量数据放在同一个底座里,少一个组件,就少一堆运维事。

当然我不是说 Redis 能完全取代专业向量数据库。数据量到千万级、高并发向量检索要求特别极端的场景,专用向量库有它的优势。但对绝大多数刚起步的 AI 应用来说,Redis 的向量能力已经够用,而且数据模型统一带来极大的便利。这个大家要根据自己的规模来判断。

1.3 Agent 运行时状态协调:从缓存到会话中枢

Agent 应用比普通 RAG 复杂得多。一个任务会被拆成多步,每一步可能要调用模型、调用工具、读取中间状态。这些中间状态放哪?数据库太重,本地内存不共享,文件系统不靠谱。Redis 的 Hash、Stream、List、分布式锁、过期时间这些能力,恰好覆盖了 Agent 运行时的全部需求:会话短期记忆、步骤状态、并发锁、速率控制。

这条路径非常有意思,也是我认为“Redis 已正式接入 AI”这句话最有分量的一层:AI 应用的运行时状态机,正在把 Redis 变成会话中枢。

1.4 AI 辅助开发与运维:反向接入

最后一类比较特别——不是 Redis 服务 AI,而是 AI 工具反过来帮开发者更好地用 Redis。实际工作中,用大模型生成 Lua 脚本、排查 Redis 慢查询、设计缓存 Key 结构,已经成了我日常的一部分。AI 写出 Redis 脚本骨架,我负责审边界条件、压测、上线,配合效率确实提升很大。这部分我也放到后面详细展开,并且会带上提示词模板和避坑提醒。

提醒一下:四种路径并不是非此即彼的关系。很多生产系统同时用 Redis 做语义缓存、向量检索、会话状态和限流。关键是你要对 Redis 的数据结构有整体认知,然后才知道每个场景该用哪种结构。

为了帮你快速建立认知,我把 AI 场景里最常用的 Redis 结构列了个对照表,拿走即用:

Redis 结构典型 AI 应用场景为什么选它
String缓存模型响应、存储 JSON 结果、限流计数简单直接,天然支持过期时间
Hash会话状态、Agent 记忆字段、用户画像可按字段单独读写,方便只更新某个状态变量
List消息队列、任务队列、Agent 步骤日志左右端推拉,顺序天然可控
Set / ZSet去重、已处理任务记录、按相似度排序ZSet 的分值可以作为热度/时间排序依据
StreamAgent 事件流、日志流、消费者组支持消费组,配合多 Worker 做任务分发
向量索引语义缓存、RAG 检索、记忆召回把相似度计算和存储放在一个系统里

2. 语义缓存落地:一次向量化查询把大模型调用挡住一大半

我在第一家公司做 AI 客服助手时,最痛的就是成本账单。上线当天没做缓存,模型调用量直接冲上去,财务看到账单都来问怎么回事。后来我给 Redis 加了一层语义缓存,效果立竿见影:热问题命中率大概在 25% 到 35%,对用户体验几乎无感知,因为命中后返回时间从两秒降到几十毫秒。这一章我把完整落地思路讲透。

2.1 精确缓存和语义缓存:差的是一个向量

传统的做法很容易理解:把用户问题原文作为 Key,模型答案作为 Value,设置 TTL。

import redis r = redis.Redis(decode_responses=True) answer = r.get(f"cache:{question}") if not answer: answer = call_llm(question) r.setex(f"cache:{question}", 300, answer)

问题很明显:用户说“怎么退钱”和“退款流程是什么”,语义几乎一样,但 Key 不一样,缓存命中率为零。于是我们引入 semantic cache:

  1. 用户问题进来,先调用 Embedding 模型,转成一个向量。比如 1536 维浮点数组。
  2. 把这个向量写入 Redis 的向量索引。
  3. 查询时用同样的 Embedding 模型把新问题向量化,然后在 Redis 里做 K 近邻相似度搜索。
  4. 如果最相似的历史问题距离低于阈值,直接把对应的历史答案返回;否则走大模型,然后入库。

核心差异就在于:精确缓存用字符串匹配,语义缓存用向量相似度匹配。

2.2 用 Redis 做语义缓存的实操代码

先建一个向量索引。假设你用的是 Redis Stack 或支持 Search 模块的 Redis 服务,可以直接用 FT.CREATE 命令:

FT.CREATE llm_cache_idx ON HASH PREFIX 1 llmcache: SCHEMA \ question TEXT \ answer TEXT \ q_vector VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE

这条命令的意思是:创建一个索引,名字叫llm_cache_idx,作用于 Hash 类型的数据,Key 前缀是llmcache:。每个 Hash 需要包含question文本、answer文本、q_vector向量三个字段,向量的维度是 1536,距离度量用余弦距离。

写入缓存时,需要把问题、答案、向量一起写进 Hash:

HSET llmcache:1b0f3a question "怎么退款" answer "您可以在订单页..." q_vector "0.0123,0.0456,...,0.0789"

查询时用 FT.SEARCH 做 KNN 向量检索:

FT.SEARCH llm_cache_idx "*=>[KNN 3 @q_vector $query_vec AS score]" \ SORTBY score ASC DIALECT 4 \ RETURN 3 question answer score \ PARAMS 2 query_vec "0.0111,0.0322,...,0.0655"

得到结果后,取最小的距离分数。如果小于你设定的阈值,就把对应答案返回;否则认为缓存未命中,调用大模型。Python 端配合 redis-py 的搜索模块或者官方 RedisVL 客户端都能实现,代码量很少。

2.3 阈值、TTL 与 Key 设计:三个参数决定成败

这个玩法看似简单,真正决定效果的是三个参数:

  • 相似度阈值。余弦距离越小代表越相似。我常用的阈值区间是 0.1 到 0.2,对应很多向量模型的相似度大约是 0.8 到 0.9。注意不同 Embedding 模型的分布不一样,不要照搬别人的阈值,最好在你自己的历史问题上采样测试。
  • TTL 时长。推荐“短期严格、长期宽松”:客服类高频问题可以缓存 5 到 15 分钟;知识库类答案可以放到几小时甚至一天。但涉及价格、库存、政策这类高频变化的内容,TTL 要压缩到 1 分钟以内,否则用户会看到过期数据。
  • Key 设计。建议用llmcache:{hash_id}这种带前缀的方式,hash_id 可以用问题的向量哈希或随机 ID,要保证可追踪性,后面查问题、清缓存都方便。

2.4 哪些场景适合语义缓存,哪些别硬上

我在项目里总结出一条经验:语义缓存适合“答案稳定、问题重复、延迟敏感”的场景。比如产品介绍、使用帮助、政策说明、常见故障排查,都是很好的对象。

反过来,下面三种场景不要硬上:

  • 答案强个性化:比如根据用户画像生成专属推荐,每个人的结果都不同,缓存命中率低且容易给出陈旧结论。
  • 强实时信息:比如“现在有没有促销”“今天天气怎么样”,命中缓存反而是灾难。
  • 涉及合规或权限差异:不同用户能看到的内容不同,缓存一条答案给所有人,会造成越权泄露,这种场景慎用。

另外,就算用了语义缓存,也一定要设置合理的最大缓存条数和内存淘汰策略,防止 Embedding 数据把内存堆爆。向量数据的体积比纯文本大得多,后面第 5 章我会专门讲 Big Key 的问题。

3. Agent 记忆与状态协调:Redis 从缓存变成会话中枢

如果说语义缓存还停留在“缓存”的舒适区,那么 Agent 场景才是 Redis 在 AI 时代真正的新身份。多个 Agent、多轮任务、中间状态、并发写入,这些需求天然适合 Redis 的数据结构和原子操作。这一章我按自己在开源 Agent 项目里沉淀的经验来写。

3.1 短期记忆用 Hash + TTL,长期记忆靠向量召回

Agent 的记忆分两层:

短期记忆:当前会话内的上下文。比如用户说“我叫小王”“帮我查明天的航班”,这些信息时效性强,只需要在当前会话内保留。用 Hash 存非常合适:

HSET agent:conversation:abc123 user_name "小王" query_time "2025-..." status "querying_flight" EXPIRE agent:conversation:abc123 1800

Hash 的好处是可以单独更新某个字段。比如 Agent 执行到“查询航班”这一步时,只需更新status,不需要把整个会话状态重新写一遍。TTL 设 30 分钟,会话结束或者用户离开后自动清理,不会留下垃圾数据。

长期记忆:跨会话的用户偏好、历史行为。比如用户每次都说“尽量选靠窗座位”,这种信息应该存下来,下次新会话开始时就召回。长期记忆不能用简单 KV 做全文匹配,更适合向量化召回——把用户历史描述向量化后存进 Redis 向量索引,新会话开始时检索最相关的历史记忆,塞进 Prompt。这里的存储结构可以复用上一章的语义缓存技术栈,只是字段从“问题/答案”换成“记忆内容/向量”。

3.2 多 Agent 并发写记忆,分布式锁终于不是面试题了

很多后端同学对 Redis 分布式锁的印象就是“面试会考,工作用不上”。但在 Agent 工程里,分布式锁真真正正成了高频组件。原因很现实:现在主流的 Agent 框架允许多个 Worker 并行处理同一个任务,或者多个线程同时更新同一个用户的记忆。如果不加锁,两个 Agent 同时读到同一个会话状态,然后各自更新,后写的覆盖先写的,会话直接乱掉。

我用的锁实现方式很经典:

import redis, uuid r = redis.Redis(decode_responses=True) def acquire_lock(lock_key: str, token: str, ttl: int = 10) -> bool: return bool(r.set(lock_key, token, nx=True, ex=ttl)) def release_lock(lock_key: str, token: str) -> bool: # 用 Lua 保证比较和删除是原子的 script = """ if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end """ return bool(r.eval(script, 1, lock_key, token))

要点就两个:加锁用SET key token NX EX一次性完成,避免分开执行导致锁超时问题;解锁用 Lua 脚本先比对 token 再删除,防止误删别人的锁。Agent 任务执行完后,马上释放锁;极端情况下业务逻辑卡住,锁也会自动过期,不会死锁。

还有一个小技巧:锁的 Key 建议用lock:agent:task:{task_id}这种细粒度命名,只锁住具体任务,不要搞一个全局大锁,否则 Agent 之间互相等待,并行能力直接废掉。

3.3 序列化是 AI 状态存储里最容易被埋的雷

Agent 状态里经常要存结构化对象,比如工具调用参数、中间结果、上下文列表。怎么存?很多人图省事直接 pickle 或者 Java 原生序列化,这是我在项目里踩过的最大坑。

先说结论:跨语言场景一律用 JSON。如果你的 Agent 只有 Python,pickle 确实方便,可一旦你想用 Java/Go 写一个消费者去读状态,甚至只是想用 redis-cli 手动排查数据,pickle 的内容根本没法看。Java 端如果用 JDK 序列化,会出现大量\xAC\xED\x00\x05这种二进制头,跨语言读取更是直接失败。我自己调试线上问题时,打开 Redis 看到一堆这种二进制垃圾,整个人都麻了。

JSON 也有一点需要注意:时间字段必须存成标准 ISO 格式,不要存 Python 的datetime默认字符串,否则不同语言解析会有偏差。另外如果对象特别大,建议拆成 Hash 的多个字段而不是存一个超大 JSON 字符串,这样修改单个字段时不需要全量读写,性能和可维护性都好得多。

3.4 Key 命名空间:从第一天就按 agent 和 session 级规划

Agent 应用通常不是单一 Agent,你可能同时有“客服 Agent”“下单 Agent”“售后 Agent”,每个 Agent 还有多个会话。如果不提前规划 Key 命名,上线一周后 Redis 里的 Key 就会变成一锅粥。

我建议从第一天开始就用三段式命名:

agent:{agent_name}:session:{session_id}:{field}

举例:

agent:cs_agent:session:abc123:mem agent:cs_agent:session:abc123:status agent:order_agent:session:def456:order_amount

这样至少有三个好处:第一,用 SCAN 就能按前缀把某个 Agent 的会话数据捞出来;第二,排查问题时能一眼看出数据属于哪个业务;第三,后续做数据清理和迁移,可以用通配匹配按 Agent 批量操作。命名规范看起来是小事,但真能帮你省下无数 Debug 时间。

4. 主从部署、Windows 开发与 AI 辅助编程:AI 时代的 Redis 环境

Redis 接入 AI 场景之后,部署和开发环境的要求也变了。以前几个缓存节点挂了影响不大,重启就行;现在 Redis 里很可能存着模型缓存和 Agent 会话状态,挂了直接导致 AI 应用大面积不可用。所以部署层面的稳定性、开发工具链、辅助编程方式,都要跟上。

4.1 为什么我建议直接上 Docker 主从而不是单点 Redis

本地开发环境单点 Redis 没问题,但凡是上了测试环境、准备联调 AI 应用,我强烈建议直接上主从架构。原因很简单:AI 应用是串行链路,模型调用后面跟着 Redis 读写,任何一步 redis 不可用,整个 Agent 任务就断了。

用 Docker Compose 拉一套主从架构非常快。下面这个配置可以直接参考:

services: redis-master: image: redis:7-alpine container_name: redis-master ports: - "6379:6379" command: ["redis-server", "--appendonly", "yes"] redis-replica: image: redis:7-alpine container_name: redis-replica ports: - "6380:6379" command: ["redis-server", "--replicaof", "redis-master", "6379", "--appendonly", "yes"] depends_on: - redis-master

主从架构解决的最大问题就是“主节点坏了,只读流量还能顶一会儿”。注意两点:第一,命令里--appendonly yes开启 AOF 持久化,防止重启丢数据;第二,主从复制是异步的,极端情况下主节点宕机时最后一小段数据可能丢失。如果业务要求更高,可以上 Sentinel 做自动故障转移,但那是生产环境的话题,开发环境用主从已经完全够了。

再多说一句:AI 应用里缓存数据可以重建,但 Agent 会话状态和数据一致性比普通缓存敏感。所以我不建议把所有 Redis 数据全部交给 LRU 自动淘汰来管理,至少要给会话状态设置明确的 Key 前缀,并对这部分数据关闭淘汰或单独设置策略,避免内存压力上来时把用户会话给挤掉。

4.2 Windows 开发环境与可视化客户端的正确选择

很多同学在 Windows 上做 AI 开发,然后发现 Redis 官方并不提供 Windows 原生版本。这里的选择很明确:

  • 开 Docker Desktop,在容器里跑 Redis,这是最推荐的方式,和 Linux 生产环境一致,避免“本地能跑、上线跑不了”的尴尬。
  • 用 WSL2 装 Redis,性能和体验都很好,适合不想太依赖 Docker 的同学。
  • 使用 Memurai 这种 Windows 原生 Redis 兼容实现,适合必须原生运行的环境。

可视化工具方面,我个人常用的是 Another Redis Desktop Manager 和 RedisInsight。前者界面清爽、跨平台,适合日常看 Key 和 Debug;后者是官方出品,对 Search 索引、向量数据、慢日志的支持更完整,调试技术问题时我更喜欢用 RedisInsight。

需要特别提醒一点:可视化工具只是用来辅助排查,千万别在 GUI 里直接乱删数据。尤其在 AI 应用里,一个友好但有误导性的 Key 名可能让你误删模型缓存或会话状态,删完后再恢复就不容易了。养成先备份再操作的习惯。

4.3 让 AI 帮你写 Redis 代码的正确姿势

“AI 接入 Redis”还有另一面:让我这种老工程师也能用 AI 快速生成 Redis 相关代码。我日常工作里有三类任务特别适合交给 AI:

  • 分布式锁、限流、幂等等通用 Redis 逻辑;
  • 缓存 Key 设计、TTL 策略选择;
  • 排查一段 Redis Lua 脚本的性能问题和边界 bug。

但 AI 生成代码从来不是零风险。我自己总结了一套提示词模板:

请用 Python redis-py 实现一个带过期时间的分布式锁,要求: 1. 加锁使用 SET key token NX EX seconds,token 用 uuid4; 2. 解锁必须用 Lua 脚本比较 token 后删除,不能直接 DEL; 3. 提供加锁失败后的重试等待逻辑,最多重试 3 次; 4. 给出完整的异常处理和资源释放代码。

拿到生成的代码后,我至少做四件事:

  1. 检查所有 Redis 命令是否用了 KEYS/ARGV 传参,有没有把值拼进命令字符串。
  2. 检查 TTL 是否合理,锁过期时间应该大于业务最大执行时间。
  3. 检查解锁逻辑是否原子,能不能防误删。
  4. 本地压测一遍,看高并发下有没有异常。

AI 辅助编程的本质是提高效率,代码质量仍然由你把关。这一点在 Redis 这种人命关天的数据组件上尤其重要。

5. 模型抖动、大 Key 与序列化:AI 场景最容易炸的 Redis 雷区

做了半年多 Redis + AI 应用,我整理了一份“最容易炸”的问题清单。这些问题在传统 Redis 场景里也有,但 AI 场景会把它放大,不提前预防,线上就要手忙脚乱。

5.1 模型服务超时,会以你意想不到的方式打崩 Redis

最常见的事故路径是这样的:大模型服务偶发超时,应用端设置了重试机制;一旦模型服务抖动,重试流量突然增大;重试请求打到缓存层,大量并发查询 Redis;Redis 本身没事,但缓存未命中的请求同时涌向模型服务,形成雪崩。等模型恢复后,Redis 里的缓存又全部过期,新一轮流量又全部穿透。

这类问题的标准解法是三板斧:

  • 给大模型调用加熔断器,连续失败 N 次直接降级,不再继续加重试压力;
  • 给语义缓存设置合理的 TTL,并在缓存 Miss 时加 jitter,避免所有请求在同一时刻穿透;
  • 对于特别昂贵的模型调用,可以缓存“模型临时不可用”的降级结果几秒钟,防止瞬间冲击。

我们在项目中做过一次压测:没有熔断时,模型返回 500 的瞬间,Redis QPS 飙升到正常值的 8 倍,部分慢查询挡住了后续业务;加上熔断和本地兜底后,整个系统在模型抖动期间依然能保证基础可用。

5.2 向量字段是怎么变成 Big Key 的

这是向量化进入 Redis 后特有的新问题。以 1536 维 float32 向量为例,一个向量大约 6KB。如果你把一组向量塞进一个 Hash,比如一万条历史记忆,这个 Hash 就接近 60MB,妥妥的 Big Key。Redis 对单个 Key 的操作是单线程的,Big Key 会导致所有客户端操作同一把“锁”,延迟瞬间拉高。

应对方案:

  • 单条向量单独作为一个 Key,不要把所有向量塞进一个 Hash。
  • 如果业务需要批量加载,按业务维度分片,比如按用户 ID 分片,每个分片控制在合理大小。
  • 定期用redis-cli --bigkeys扫描,把新增的大 Key 揪出来。

Big Key 在 AI 场景比传统业务更容易被忽略,因为业务量看起来不大,但向量体积不小,一不留神就把内存和延迟吃掉了。

5.3 序列化兼容:跨语言读缓存前先想清楚

前面提过 Agent 状态序列化的坑,这里再展开说一个典型案例。你有一个 Python 写的 Agent 服务,另一方有一个 Java 写的报表服务,两边共享同一个 Redis。Python 服务把模型结果用 pickle 写进 Redis,Java 服务读取时直接乱码。排查很久才发现是序列化问题。

我在项目上定的规矩很简单:

  • 通用数据一律用 JSON 序列化;
  • 必须用二进制序列化时,明确约定数据格式和协议版本;
  • 禁止在跨服务共享的缓存里使用语言默认原生序列化。

JSON 的体积可能比二进制大一些,但换来的是跨语言可读、可排查、可版本迭代。这个代价值得。

5.4 那些 Redis 面试题,AI 场景下的新问法

这些年 Redis 面试题翻来覆去就是缓存穿透、击穿、雪崩,分布式锁,主从一致性。AI 场景下这些题并没有消失,而是换了个马甲:

  • “大模型接口超时重试导致缓存雪崩怎么处理?”——问的是雪崩,但场景更具体。
  • “Agent 会话状态用 Redis 的什么结构存?”——问的是哈希和序列化。
  • “多 Agent 并发写用户记忆,怎么保证不覆盖?”——问的是分布式锁和乐观锁。
  • “语义缓存的 TTL 应该设多少?”——问的是业务理解与缓存策略权衡。

如果你是为了面试准备,别只顾着背原题,多想想这些应用场景。能结合 AI 场景把原理讲清楚,比单纯背出“Redis 单线程为什么快”更能体现水平。

6. 用 AI 生成 Lua 脚本,把 Redis 的原子能力变成日常操作

最后一章,我想认真聊聊 AI 写 Redis Lua 脚本这个实操方向。这既是我体验最深的部分,也是我认为“Redis 已正式接入 AI”落实到个人工作流之后最明显的收益点。

6.1 Lua 脚本和 AI 编程为什么合拍

Redis 的 Lua 脚本有一个核心价值:原子性。脚本执行期间不会插入其他命令,多个命令要么全部成功要么全部失败。在 AI 应用里,限流、计数、状态更新、锁释放,往往都需要这种“要么不做要么做完整”的原子语义。但 Lua 脚本写起来有不少细节:KEYS 和 ARGV 的传参方式、返回值类型、Redis 命令在 Lua 里的调用语法。这些细节对很多人来说是有一定学习成本的,而 AI 大模型最擅长的恰恰就是生成这种短小、模式化、规则明确的代码片段。

我在项目里的习惯是:让 AI 先出一版完整脚本,再请它用通俗语言解释逻辑,最后我拿几个关键场景做测试。遇到 bug 时,直接让 AI 根据报错信息修订。这套流程已经帮我处理了限流、幂等、防重等多个需求。

6.2 一个令牌桶限流脚本的生成与审查过程

先看一个典型的 AI 生成的令牌桶限流 Lua 脚本。这个脚本是简化版,重点演示思路:

-- KEYS[1]: 限流 key -- ARGV[1]: 桶容量 -- ARGV[2]: 每秒恢复速率 -- ARGV[3]: 当前毫秒时间戳 local key = KEYS[1] local capacity = tonumber(ARGV[1]) local rate = tonumber(ARGV[2]) local now = tonumber(ARGV[3]) local token_key = key .. ":tokens" local ts_key = key .. ":ts" local tokens = tonumber(redis.call("GET", token_key)) if not tokens then tokens = capacity end local last = tonumber(redis.call("GET", ts_key)) if not last then last = now end -- 计算从上次到现在恢复的令牌数 local delta = math.max(0, now - last) / 1000 * rate tokens = math.min(capacity, tokens + delta) -- 无论是否通过,都要更新时间戳,避免下次重复计算 redis.call("SET", ts_key, now, "EX", 3600) if tokens < 1 then redis.call("SET", token_key, tokens, "EX", 3600) return 0 end tokens = tokens - 1 redis.call("SET", token_key, tokens, "EX", 3600) return 1

这个脚本关键点有三个:一是令牌补充计算必须用毫秒差乘以速率;二是无论请求是否被限流,都要更新时间戳,否则下一次请求会把这段时间恢复的令牌又计算一遍,导致限流失效;三是所有内部 Key 都设置 EX,防止长时间不使用的数据占内存。

拿到 AI 生成的脚本后,我一般会在 redis-cli 里先用 EVAL 跑几个边界用例:第一次调用、连续调用超过容量、停顿一秒后恢复、并发调用。确认这四个场景的结果都符合预期,才会集成到代码里。

6.3 AI 写 Lua 的常见翻车点,以及我的使用习惯

AI 生成 Lua 脚本虽然快,翻车点也很集中:

  • 参数拼接:有些生成结果会在脚本内部用拼接字符串的方式生成 Key 或命令参数,这是大忌,会导致注入风险和性能问题。必须改成 KEYS/ARGV 传参。
  • 返回值类型混淆:Redis 的 RESP 协议在不同版本下对空值、数组、数字的处理有细微差异。AI 有时会把空值判断写成nil和false混淆。
  • 忽略脚本传播方式:Redis 主从架构下,脚本可能在副本上重放执行。如果脚本依赖时间或随机数,可能导致主从数据不一致。生产环境要特别注意,必要时改用纯命令组合或 Redis 7 的 Functions 特性来管理。

我自己现在写 Redis 复杂逻辑的习惯是:先是让 AI 生成一版骨架,然后重点审查边界条件和异常分支,再用真实流量做一轮压测。这大概就是“Redis 已正式接入 AI”在我这里的真实含义——不是让 Redis 变成 AI,而是让 AI 变成 Redis 的上层大脑,Redis 继续干它最擅长的事:把状态、缓存和并发协调稳到毫秒级。

如果你正在做 AI 应用,别只盯着模型本身,把 Redis 这层数据底座用好,你会少踩很多坑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 4:59:27

ThinkPHP实战:开源微信AI在线客服系统源码拆解与部署指南

最近在翻开源社区的时候看到一个挺有意思的项目&#xff1a;基于ThinkPHP的微信AI在线客服系统&#xff0c;完整前后端&#xff0c;标题上还标着“学习参考不错”。我花了点时间把源码捋了一遍&#xff0c;发现它确实不是那种凑数仓库&#xff0c;不管是做毕设、练手&#xff0…

作者头像 李华
网站建设 2026/9/30 4:59:27

大模型推理显存优化:PagedAttention与前缀缓存实战

1. 大模型推理的显存瓶颈到底卡在哪里做推理服务的人迟早会撞上一堵墙&#xff1a;模型权重明明只占十几GB&#xff0c;但并发一上来&#xff0c;显存就像漏水的桶一样往下掉&#xff0c;最后OOM&#xff08;Out of Memory&#xff09;报错把服务打挂。很多人第一反应是“模型太…

作者头像 李华
网站建设 2026/9/30 4:59:27

科研AI Agent复现困境:用PROJECT.md构建可复现工作流

1. 科研场景下 AI Agent 的真实困境1.1 从“能跑通”到“能复现”之间的鸿沟我接触 AI Agent 辅助科研这件事&#xff0c;最早是从跑通一个文献综述的小流程开始的。当时觉得挺爽&#xff1a;把几篇 PDF 丢进去&#xff0c;Agent 自动抽取方法、数据集、结论&#xff0c;生成一…

作者头像 李华
网站建设 2026/9/30 4:59:19

URP管线PBR渲染实战:从BRDF原理到Shader实现与调参

1. 从零理解PBR&#xff1a;为什么它成了现代渲染的默认答案第一次接触PBR&#xff08;Physically Based Rendering&#xff0c;基于物理的渲染&#xff09;是在做一个室内场景项目的时候。当时用传统的手调高光贴图方式&#xff0c;金属看起来像塑料&#xff0c;塑料看起来像纸…

作者头像 李华
网站建设 2026/9/30 4:58:49

AI课程作业实战:ABC理论、偏见分析与猫狗分类全复盘

1. 作业拆解&#xff1a;先搞清楚这门课到底想考你什么1.1 从“作业3”说起&#xff1a;这门课的考核节奏与隐藏逻辑坦白说&#xff0c;第一次看到《人工智能》课程作业3这个题目时&#xff0c;我脑子里是有点懵的。倒不是题目本身有多难&#xff0c;而是这类课程作业和数学、物…

作者头像 李华
网站建设 2026/9/30 4:58:28

基于Java+MySQL+SSM的勤工助学管理系统实战:从建表到联调

简介&#xff1a;这份资源是面向高校计算机相关专业学生与教学管理人员的勤工助学管理系统毕业设计文档&#xff0c;采用Java语言结合MySQL数据库开发&#xff0c;技术栈涵盖SSM框架&#xff08;Spring、SpringMVC、MyBatis&#xff09;&#xff0c;适合作为课程设计、毕业设计…

作者头像 李华