当前位置:首页>python>Python+LangChain/LangGraph框架开发Ai智能体系列��29节 | LangGraph Checkpointer接口实现Redis存储持久化入门指南

Python+LangChain/LangGraph框架开发Ai智能体系列��29节 | LangGraph Checkpointer接口实现Redis存储持久化入门指南

  • 2026-07-03 21:09:54
Python+LangChain/LangGraph框架开发Ai智能体系列��29节 | LangGraph Checkpointer接口实现Redis存储持久化入门指南

目标:让 AI Agent 记住对话历史,服务重启也不丢失


1. 学习目标

目标
说明
理解 Checkpointer 原理
什么是状态持久化,为什么需要
自定义 Checkpointer
继承 BaseCheckpointSaver,用 Redis 存储
实现多用户隔离
用 thread_id区分不同用户的对话
验证持久化效果
服务重启后能恢复历史状态

2. 核心概念

Checkpointer(检查点器) 作用:保存 Agent 的运行状态,下次运行时恢复

类比:游戏存档

  • 每打完一关自动存档(put)
  • 下次打开游戏从存档继续(get)
  • 查看历史存档(list)
概念
含义
thread_id
用户唯一标识(如 open_id),决定状态隔离粒度
checkpoint
某一时刻的完整状态快照
TTL
过期时间,自动清理旧数据(如 7 天)
BaseCheckpointSaver
LangGraph 提供的抽象基类

3. 技术架构概览

架构图:

用户请求  ↓LangGraph Agent(StateGraph)  ├─ 自动调用 checkpointer.get() 恢复历史  ├─ 执行 agent 节点(LLM 调用)  └─ 自动调用 checkpointer.put() 保存状态  ↓Redis Checkpointer  ├─ Redis Hash 存储(Key = langgraph:checkpoint:{thread_id})  ├─ pickle 序列化状态快照  ├─ TTL = 7 天自动过期  └─ 最多保留 50 个快照

调用流程图:


4. 代码分段说明

4.1 定义 Agent 状态

classAgentState(TypedDict):    messages: Annotated[list[BaseMessage], add_messages]

解释:定义 Agent 的状态结构,messages是消息列表,add_messages是累加器(每次新消息追加到列表)。


4.2 核心:Redis Checkpointer

classRedisCheckpointSaver(BaseCheckpointSaver):def__init__(self, redis_url, ttl_seconds=604800):        self.client = redis_lib.Redis.from_url(redis_url, decode_responses=False)        self.ttl = ttl_seconds  # 默认 7 天过期

解释:初始化 Redis 连接,decode_responses=False 表示返回原始字节(因为用 pickle 序列化)。


4.3 生成 Redis Key

def_make_key(self, thread_id: str) -> str:returnf"langgraph:checkpoint:{thread_id}"

解释:每个用户的对话存在独立的 Redis key 下,实现数据隔离。


4.4 读取状态:get()

defget(self, config: dict) -> Optional[CheckpointTuple]:    thread_id = config.get("configurable", {}).get("thread_id""default")    key = self._make_key(thread_id)    all_fields = self.client.hgetall(key)  # 获取该用户所有快照ifnot all_fields:returnNone# 按 checkpoint_id 降序,取最新    latest_id = sorted(all_fields.keys(), reverse=True)[0]    raw = all_fields[latest_id]    data = self._deserialize(raw)  # pickle 反序列化return CheckpointTuple(config=..., checkpoint=..., metadata=...)

解释

  1. 根据 thread_id找到 Redis key
  2. HGETALL
     获取所有历史快照
  3. 按时间排序,取最新的一个
  4. pickle.loads
     反序列化,返回 CheckpointTuple

4.5 保存状态:put()

defput(self, config, checkpoint, metadata, new_versions) -> dict:    thread_id = config.get("configurable", {}).get("thread_id""default")    key = self._make_key(thread_id)    checkpoint_id = checkpoint.get("id")    data = {"channel_values": checkpoint.get("channel_values", {}),"metadata": metadata,        ...    }    self.client.hset(key, checkpoint_id, self._serialize(data))  # pickle 序列化后存储    self.client.expire(key, self.ttl)  # 刷新 TTL# 只保留最近 50 个快照iflen(all_fields) > 50:        oldest_fields = sorted(all_fields)[:-50]        self.client.hdel(key, *oldest_fields)

解释

  1. 提取 checkpoint 中的关键数据
  2. pickle.dumps
     序列化后用 HSET存储
  3. 设置/刷新 TTL,自动过期
  4. 限制快照数量,防止 Redis 无限膨胀

4.6 列出历史:list()

deflist(self, config: dict) -> Iterator[CheckpointTuple]:    thread_id = config.get("configurable", {}).get("thread_id""default")    key = self._make_key(thread_id)    all_fields = self.client.hgetall(key)for field_id insorted(all_fields.keys(), reverse=True):yield CheckpointTuple(...)  # 用 yield 返回迭代器

解释:返回所有历史快照的迭代器(而非一次性加载全部),节省内存。


4.7 删除数据:adelete()

asyncdefadelete(self, config: dict) -> None:    thread_id = config.get("configurable", {}).get("thread_id""default")    key = self._make_key(thread_id)    result = self.client.delete(key)  # 删除整个 key

解释:删除用户的所有对话数据,用于账号注销或测试清理。


4.8 构建 Agent

defbuild_agent_with_checkpointer(checkpointer):defcall_model(state: AgentState) -> dict:        messages = state["messages"]        response = llm.invoke(messages)return {"messages": [response]}    graph = StateGraph(AgentState)    graph.add_node("agent", call_model)    graph.add_edge(START, "agent")    graph.add_edge("agent", END)    compiled = graph.compile(checkpointer=checkpointer)  # ← 关键:注入 checkpointerreturn compiled

解释

  1. 定义模型调用函数
  2. 构建 StateGraph
  3. compile(checkpointer=...)
     时注入 checkpointer
  4. LangGraph 自动在每次调用前后读写状态

4.9 调用示例

config = {"configurable": {"thread_id""user_001"}}# 第一次对话result = agent.invoke(    {"messages": [HumanMessage(content="你好")]},    config=config)# LangGraph 自动调用 checkpointer.put() 保存状态# 第二次对话(自动带上历史)result = agent.invoke(    {"messages": [HumanMessage(content="还记得我吗?")]},    config=config)# LangGraph 自动调用 checkpointer.get() 恢复历史

5. 知识总结

一句话总结 Checkpointer 让 Agent 记住对话,Redis 实现持久化,thread_id 实现多用户隔离。

知识点
关键点
为什么需要 Checkpointer
服务重启后对话不丢失,实现"记忆"
为什么用 Redis
分布式存储 + TTL 自动清理 + 并发安全
thread_id 的作用
用户唯一标识,不同用户数据完全隔离
pickle vs JSON
pickle 体积小但不可读,JSON 可读但占空间
TTL 过期
默认 7 天无活动自动删除,节省 Redis 空间
快照数量限制
最多保留 50 个,防止数据膨胀

Q: LangGraph 状态存在哪?服务重启怎么办?

A: 用 Checkpointer 接口,开发用 MemorySaver(重启丢),生产用 RedisCheckpointSaver。Redis 方案:序列化 State → pickle → 存 Redis Hash,key = checkpoint:{thread_id}:{checkpoint_id},设置 TTL 自动过期。


6. 完整代码示例

6.1 本节所有源代码(复制直接运行,有问题下方扫码加入微信技术交流群)

"""实现==============================目标:自定义 LangGraph BaseCheckpointSaver,用 Redis 做后端存储特性:TTL 自动过期 / 序列化快照 / 多 checkpoint 版本管理依赖:pip install redis langgraph langchain-openai"""import sysimport ioimport osimport jsonimport pickleimport asynciofrom typing import Any, Iterator, OptionalTuplefrom datetime import datetimefrom langgraph.checkpoint.base import BaseCheckpointSaver, Checkpoint, CheckpointMetadata, CheckpointTuplesys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')# ─── 尝试导入 Redis ──────────────────────────────────────────────────────────try:    import redis as redis_lib    REDIS_AVAILABLE = Trueexcept ImportError:    REDIS_AVAILABLE = False    print("[WARN] redis 未安装,将使用 MemorySaver 演示")from typing import Annotatedfrom typing_extensions import TypedDictfrom langgraph.graph import StateGraph, START, ENDfrom langgraph.graph.message import add_messagesfrom langgraph.checkpoint.memory import MemorySaverfrom langchain_core.messages import HumanMessage, AIMessage, BaseMessagefrom dotenv import load_dotenvload_dotenv()# ─── 1. 自定义 Redis Checkpointer ────────────────────────────────────────────class RedisCheckpointSaver(BaseCheckpointSaver):    """    基于 Redis 的 LangGraph Checkpointer    存储结构:      redis hash key:   checkpoint:{thread_id}      hash field:       {checkpoint_id}      hash value:       pickle({"messages": [...], "metadata": {...}})    TTL:默认 7 天(604800 秒)    """    def __init__(self, redis_url: str = "redis://localhost:6379", ttl_seconds: int = 604800):        if not REDIS_AVAILABLE:            raise ImportError("请先 pip install redis")        self.client = redis_lib.Redis.from_url(redis_url, decode_responses=False)        self.ttl = ttl_seconds        print(f"[Redis] 已连接:{redis_url}")    def _make_key(self, thread_id: str) -> str:        return f"langgraph:checkpoint:{thread_id}"    def _serialize(self, data: Any) -> bytes:        return pickle.dumps(data)    def _deserialize(self, raw: bytes) -> Any:        return pickle.loads(raw)    # ─── 核心接口:get(读取最新快照)    def get(self, config: dict) -> Optional[CheckpointTuple]:        """读取最新 checkpoint,返回 CheckpointTuple(state, metadata, config)"""        thread_id = config.get("configurable", {}).get("thread_id""default")        checkpoint_ns = config.get("configurable", {}).get("checkpoint_ns""")        key = self._make_key(thread_id)        # 获取所有 checkpoint,取最新(按 checkpoint_id 排序)        all_fields = self.client.hgetall(key)        if not all_fields:            return None        # 按 checkpoint_id 降序,取最新        latest_id = sorted(all_fields.keys(), reverse=True)[0]        raw = all_fields[latest_id]        data = self._deserialize(raw)        # checkpoint_id 应该是字符串 UUID 格式        checkpoint_id_str = latest_id.decode() if isinstance(latest_id, byteselse latest_id        # 构建 Checkpoint(TypedDict 格式)        checkpoint = {            "v": data.get("v"2),            "id": checkpoint_id_str,            "ts": data.get("ts", datetime.now().isoformat()),            "channel_values": data.get("channel_values", {}),            "channel_versions": data.get("channel_versions", {}),            "versions_seen": data.get("versions_seen", {}),            "updated_channels": data.get("updated_channels", {}),        }        # 构建 metadata        metadata_dict = data.get("metadata", {})        metadata = CheckpointMetadata(**metadata_dict) if isinstance(metadata_dict, dictelse CheckpointMetadata()        new_config = {            "configurable": {                "thread_id": thread_id,                "checkpoint_ns": checkpoint_ns,                "checkpoint_id": checkpoint_id_str,            }        }        return CheckpointTuple(            config=new_config,            checkpoint=checkpoint,            metadata=metadata        )    def get_tuple(self, config: dict) -> Optional[CheckpointTuple]:        """get_tuple 接口(LangGraph 调用)"""        return self.get(config)    # ─── 核心接口:put(写入快照)    def put(        self,        config: dict,        checkpoint: Checkpoint,        metadata: CheckpointMetadata,        new_versions: dict    ) -> dict:        """写入 checkpoint,返回新的 config"""        thread_id = config.get("configurable", {}).get("thread_id""default")        checkpoint_ns = config.get("configurable", {}).get("checkpoint_ns""")        key = self._make_key(thread_id)        # checkpoint_id 是字符串 UUID 格式        checkpoint_id = checkpoint.get("id"or ""        # 保存完整的 Checkpoint 字段        data = {            "v": checkpoint.get("v"2),            "id": checkpoint_id,            "ts": checkpoint.get("ts", datetime.now().isoformat()),            "channel_values": checkpoint.get("channel_values", {}),            "channel_versions": checkpoint.get("channel_versions", {}),            "versions_seen": checkpoint.get("versions_seen", {}),            "updated_channels": checkpoint.get("updated_channels", {}),            "metadata": metadata if hasattr(metadata, '__dict__'else dict(metadata or {}),        }        self.client.hset(key, checkpoint_id, self._serialize(data))        self.client.expire(key, self.ttl)  # 刷新 TTL        # 只保留最近 50 个 checkpoint,防止无限增长        all_fields = self.client.hkeys(key)        if len(all_fields) > 50:            oldest_fields = sorted(all_fields)[:-50]            if oldest_fields:                self.client.hdel(key, *oldest_fields)        return {"configurable": {"thread_id": thread_id, "checkpoint_ns": checkpoint_ns, "checkpoint_id": checkpoint_id}}    def put_writes(        self,        config: dict,        writes: list,        task_id: str,        task_path: str = ""    ) -> None:        """写入 pending writes(LangGraph 内部使用)"""        # 对于简单的实现,这里可以忽略        # 复杂实现需要将这些写入存储起来        pass    # ─── 列出所有历史快照    def list(self, config: dict) -> Iterator[CheckpointTuple]:        """列出 thread 的所有 checkpoint,返回迭代器"""        thread_id = config.get("configurable", {}).get("thread_id""default")        checkpoint_ns = config.get("configurable", {}).get("checkpoint_ns""")        key = self._make_key(thread_id)        all_fields = self.client.hgetall(key)        for field_id in sorted(all_fields.keys(), reverse=True):            # 转换为字符串            field_id_str = field_id.decode() if isinstance(field_id, byteselse field_id            raw = all_fields[field_id]            data = self._deserialize(raw)            # 构建 Checkpoint(TypedDict 格式)            checkpoint = {                "v": data.get("v"2),                "id": field_id_str,                "ts": data.get("ts", datetime.now().isoformat()),                "channel_values": data.get("channel_values", {}),                "channel_versions": data.get("channel_versions", {}),                "versions_seen": data.get("versions_seen", {}),                "updated_channels": data.get("updated_channels", {}),            }            # 构建 metadata            metadata_dict = data.get("metadata", {})            metadata = CheckpointMetadata(**metadata_dict) if isinstance(metadata_dict, dictelse CheckpointMetadata()            new_config = {                "configurable": {                    "thread_id": thread_id,                    "checkpoint_ns": checkpoint_ns,                    "checkpoint_id": field_id_str                }            }            yield CheckpointTuple(                config=new_config,                checkpoint=checkpoint,                metadata=metadata            )    # ─── 删除用户所有数据    async def adelete(self, config: dict) -> None:        """删除用户的所有 checkpoint(用于账号注销 / 测试清理)"""        thread_id = config.get("configurable", {}).get("thread_id""default")        key = self._make_key(thread_id)        result = self.client.delete(key)        print(f"[Redis] 已删除 thread_id={thread_id},删除条数={result}")    # ─── 调试:打印用户状态摘要    def inspect_thread(self, thread_id: str) -> None:        """打印用户的对话历史摘要"""        config = {"configurable": {"thread_id": thread_id}}        checkpoints = list(self.list(config))        print(f"\n[Redis 状态检查] thread_id={thread_id}")        print(f"  checkpoint 数量:{len(checkpoints)}")        if checkpoints:            latest = checkpoints[0]            state = latest.checkpoint.get("channel_values", {}) if hasattr(latest, 'checkpoint'else latest.get("state", {})            messages = state.get("messages", []) if isinstance(state, dictelse []            print(f"  最新消息数:{len(messages)}")            for msg in messages[-3:]:  # 只看最后 3 条                if isinstance(msg, dict):                    role = msg.get("type""?")                    content = str(msg.get("content"""))[:60]                else:                    role = type(msg).__name__                    content = str(getattr(msg, "content"""))[:60]                print(f"    [{role}{content}")# ─── 2. 简单 Agent(带 Redis Checkpointer)────────────────────────────────────class AgentState(TypedDict):    messages: Annotated[list[BaseMessage], add_messages]def build_agent_with_checkpointer(checkpointer):    """构建带 checkpointer 的 LangGraph Agent(支持多轮对话记忆)"""    # 尝试使用 llama.cpp,失败则回退到 Mock    llm = None    try:        from langchain_openai import ChatOpenAI        llm = ChatOpenAI(base_url="http://localhost:8080/v1", api_key="not-needed", model="qwen3.5-4b-q4_k_m", temperature=0.7)        print("[Agent] 使用 llama.cpp qwen3.5-4b-q4_k_m")    except Exception as e:        print(f"[Agent] llama.cpp 不可用({e}),使用 Mock LLM")    def call_model(state: AgentState) -> dict:        messages = state["messages"]        if llm:            import re            response = llm.invoke(messages)            # 去除 qwen3 的 <tool_call> 标签            clean = re.sub(r"<tool_call>.*?<tool_call>""", response.content, flags=re.DOTALL).strip()            response.content = clean            return {"messages": [response]}        else:            # Mock 回复            last_msg = messages[-1].content if messages else "..."            return {"messages": [AIMessage(content=f"[Mock 回复] 我收到了:{last_msg[:30]}")]}    graph = StateGraph(AgentState)    graph.add_node("agent", call_model)    graph.add_edge(START, "agent")    graph.add_edge("agent", END)    compiled = graph.compile(checkpointer=checkpointer)    return compiled# ─── 3. 演示:Redis 多轮对话 ──────────────────────────────────────────────────def demo_redis_chat(agent, checkpointer, thread_id: str, messages: list[str]) -> None:    """模拟一个用户的多轮对话"""    config = {"configurable": {"thread_id": thread_id}}    print(f"\n{'='*50}")    print(f"用户 {thread_id} 开始对话")    print(f"{'='*50}")    for msg in messages:        print(f"\n[用户] {msg}")        result = agent.invoke(            {"messages": [HumanMessage(content=msg)]},            config=config        )        last_ai = result["messages"][-1].content        print(f"[AI] {last_ai[:100]}")    # 检查持久化状态    if hasattr(checkpointer, "inspect_thread"):        checkpointer.inspect_thread(thread_id)def demo_persistence(agent, checkpointer, thread_id: str) -> None:    """验证重启后状态恢复"""    config = {"configurable": {"thread_id": thread_id}}    print(f"\n--- 验证持久化:从 Redis 恢复 thread_id={thread_id} ---")    saved_state = checkpointer.get(config)    if saved_state:        # CheckpointTuple.checkpoint['channel_values'] 包含实际状态        channel_values = saved_state.checkpoint.get("channel_values", {})        messages = channel_values.get("messages", [])        print(f"  成功恢复 {len(messages)} 条消息记录")    else:        print("  未找到持久化数据(可能是 Redis 未连接)")# ─── Main ────────────────────────────────────────────────────────────────────def main():    print("=" * 60)    print("T13-01: Redis Checkpointer 演示")    print("=" * 60)    # ── 选择 Checkpointer    if REDIS_AVAILABLE:        try:            checkpointer = RedisCheckpointSaver("redis://localhost:6379", ttl_seconds=86400)            # 测试连接            checkpointer.client.ping()            print("[OK] Redis 连接成功")        except Exception as e:            print(f"[WARN] Redis 连接失败({e}),降级使用 MemorySaver")            checkpointer = MemorySaver()    else:        print("[INFO] 使用 MemorySaver(无 Redis)")        checkpointer = MemorySaver()    # ── 构建 Agent    agent = build_agent_with_checkpointer(checkpointer)    # ── 用户 A 对话    demo_redis_chat(agent, checkpointer, "user_alice_001", [        "你好,我叫 Alice,是一名前端工程师",        "我最感兴趣的技术是 React 和 TypeScript",        "你还记得我的名字和职业吗?",    ])    # ── 用户 B 对话    demo_redis_chat(agent, checkpointer, "user_bob_002", [        "我是 Bob,后端工程师,Python 是我的主语言",        "我最近在学 FastAPI 和 LangGraph",    ])    # ── 验证持久化    demo_persistence(agent, checkpointer, "user_alice_001")    # ── 如果是 Redis,展示存储统计    if isinstance(checkpointer, RedisCheckpointSaver):        alice_cps = checkpointer.list({"configurable": {"thread_id""user_alice_001"}})        print(f"\n[统计] Alice 共有 {len(alice_cps)} 个 checkpoint 快照存在 Redis 中")        print("[演示完成] 实际部署时 Redis 数据将在重启后保留")if __name__ == "__main__":    main()

热点文章推荐:
Hermes核心内置技能Skills快速一览(一眼定位到所需工具)
Python+LangChain/LangGraph框架开发Ai智能体系列🤖27节 | LangGraph Agent 封装为 REST API

扫码入群获取源码,后续分享更多系列教程关注公众号探索更多精彩内容

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 21:57:57 HTTP/2.0 GET : https://f.mffb.com.cn/a/493995.html
  2. 运行时间 : 0.243719s [ 吞吐率:4.10req/s ] 内存消耗:4,667.02kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=c1f6836a24719f42f1d40f5a480eede9
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000892s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000638s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000310s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000281s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000548s ]
  6. SELECT * FROM `set` [ RunTime:0.000199s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000584s ]
  8. SELECT * FROM `article` WHERE `id` = 493995 LIMIT 1 [ RunTime:0.008318s ]
  9. UPDATE `article` SET `lasttime` = 1783087077 WHERE `id` = 493995 [ RunTime:0.002101s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000308s ]
  11. SELECT * FROM `article` WHERE `id` < 493995 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000414s ]
  12. SELECT * FROM `article` WHERE `id` > 493995 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000408s ]
  13. SELECT * FROM `article` WHERE `id` < 493995 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.020500s ]
  14. SELECT * FROM `article` WHERE `id` < 493995 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.029249s ]
  15. SELECT * FROM `article` WHERE `id` < 493995 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.025827s ]
0.245390s