Agent会话数据存储方案,Redis缓存热会话

当Agent服务需要处理大量用户会话时,最稳妥的存储方式是“Redis缓存热会话,MySQL持久化全量数据”。
Redis负责扛住高频读写,MySQL负责兜底保存最终记录,即使Redis重启或淘汰旧数据,会话历史也不会丢。
本文面向零基础运维,用可执行的命令和配置演示这套方案怎么落地。

先想清楚:热会话和持久化分别解决什么问题

Agent会话通常会有两种状态:正在活跃交互的和已经结束或长期不动的。
活跃会话每次请求都要读取上下文,如果直接查MySQL,几十万条历史记录堆在一起,响应会越来越慢。
Redis把当前活跃的会话放内存里,读写速度能到微秒级;
MySQL只做最终落库,定期或异步把Redis里的会话同步过去,相当于给数据加了保险。

准备条件:一台服务器和两个基础服务

你不需要从零搭环境,只需确认以下内容已就绪:

  • Linux服务器(CentOS 7+ 或 Ubuntu 20.04+)
  • Redis 5.0+,已启动并能设置密码
  • MySQL 5.7+,已有可用的数据库和账号
  • 服务端语言环境,本文用Python 3演示,其他语言逻辑一样

可以用下面的命令检查服务是否正常:

redis-cli -a 你的密码 ping
mysql -u用户名 -p -e "select 1"

核心操作:建表、连Redis、写会话读写逻辑

1. 在MySQL创建会话表

会话表只需要记录四个关键字段:会话ID、会话内容(JSON格式)、更新时间、过期时间。
执行下面的SQL:

CREATE TABLE agent_session (
  session_id VARCHAR(64) PRIMARY KEY,
  data JSON NOT NULL,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  expire_at DATETIME NOT NULL,
  INDEX idx_expire_at (expire_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

idx_expire_at 这个索引一定不能省,否则清理过期会话时会全表扫描。

2. Redis连接与热会话读写

在Python里使用 redis-py,连接后写入会话时先操作Redis,再异步写MySQL。
核心逻辑如下:

import redis, json, pymysql
from datetime import datetime, timedelta

# 连接Redis
r = redis.Redis(host='127.0.0.1', port=6379, password='你的密码', db=0)

def get_session(session_id):
    # 先从Redis热缓存里取
    data = r.get(f"agent:session:{session_id}")
    if data:
        return json.loads(data)
    # Redis没命中,回源MySQL并重新缓存
    conn = pymysql.connect(host='127.0.0.1', user='root', password='数据库密码', database='mydb')
    with conn.cursor() as cur:
        cur.execute("SELECT data FROM agent_session WHERE session_id=%s", (session_id,))
        row = cur.fetchone()
        if row:
            r.setex(f"agent:session:{session_id}", 1800, json.dumps(row[0]))
            return row[0]
    return None

def save_session(session_id, data):
    # 写Redis,过期时间设30分钟
    r.setex(f"agent:session:{session_id}", 1800, json.dumps(data))
    # 写MySQL,过期时间设为7天后
    expire = datetime.now() + timedelta(days=7)
    conn = pymysql.connect(host='127.0.0.1', user='root', password='数据库密码', database='mydb')
    with conn.cursor() as cur:
        sql = "INSERT INTO agent_session (session_id, data, expire_at) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE data=%s, expire_at=%s"
        cur.execute(sql, (session_id, json.dumps(data), expire, json.dumps(data), expire))
    conn.commit()

这里给Redis键设置了1800秒过期,也就是热会话在内存里只保留30分钟。
Agent和用户连续对话时,每次读写都会刷新这个过期时间;
一旦对话中断超过30分钟,Redis里的键自动消失,后续请求回源MySQL,重新加载数据并再放进Redis。

3. MySQL定时清理过期会话

为了让MySQL不无限膨胀,可以写一个定时任务,每天删除已过期的会话:

mysql -u用户名 -p密码 -e "DELETE FROM agent_session WHERE expire_at < NOW();"

建议放到crontab里每天凌晨执行一次,避免手工操作。

避坑指南:这五个问题最容易踩

  • Redis不要开持久化兜底热会话。Redis只是缓存,即使开了AOF重启后恢复,也容易和MySQL数据不一致;正确做法是让MySQL作为唯一权威数据源。
  • 设置内存淘汰策略时别选noeviction。否则Redis内存满了会直接报错。建议用maxmemory-policy volatile-lru,只淘汰带过期时间的键,正好把旧会话腾出去。
  • MySQL的data字段用JSON类型前要确认版本。MySQL 5.7才开始支持JSON,5.6只能改用TEXT,否则建表会报语法错误。
  • Redis和MySQL写入顺序不能反。先写Redis成功后再写MySQL,如果MySQL失败要能回滚Redis键,避免缓存里出现脏数据。
  • 会话ID一定要用索引。如果Agent会话量一天超过几万条,不加索引的WHERE session_id=...查询会拖垮数据库。

验证方案:两条命令确认数据流动正常

先跑一段Python代码写入一个测试会话:

save_session("test123", {"name": "agent_demo", "step": 1})

然后从Redis里读取并检查键是否存在:

redis-cli -a 你的密码 get "agent:session:test123"

正常情况下返回JSON字符串。
再把Redis里的键删掉,模拟热缓存失效:

redis-cli -a 你的密码 del "agent:session:test123"

再次调用get_session("test123"),看是否能从MySQL回源并重新写入Redis。
最后检查MySQL表:

SELECT * FROM agent_session WHERE session_id='test123';

能查到完整数据且updated_at时间正确,说明这套“Redis缓存热会话、MySQL持久化”的方案已经正常运转。

如果你在配置时遇到Redis连不上、MySQL字符集乱码或数据不同步的报错,优先检查连接密码、数据库字符集和时间字段的默认值。
整体跑通后,可以根据业务峰值调整Redis过期时间和MySQL清理周期,让二者保持在最舒服的配合状态。

分享到:
上一篇
向量库备份定时脚本,防止向量数据丢失事故
下一篇
LLMOps CI/CD流水线,模型版本管理
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意