状态数据库与FTS索引双重防线:日志回放与重建恢复实战

先讲一个我上周凌晨三点碰到的事:某服务的状态数据库在滚动重启时,发现全文搜索(FTS)索引文件损坏。状态库本体通过预写日志正常恢复,数据一条没丢,但所有依赖搜索的接口全部报错,用户查不到任何记录。折腾了将近五个小时才把索引重建完并切换过去。事后复盘,问题不在“数据丢没丢”,而在“恢复手段是不是只有一条路”。这恰好就是标题里“双重防线”想表达的核心:一份数据,两条独立的恢复路径,主数据靠日志和快照兜底,派生数据靠重建对齐兜底,两个体系互不依赖,才能在故障发生时不互相拖累。

我维护的这套组件叫 Hermes State DB,听名字就知道它专门负责存“状态”的——任务进度、设备登记、在线标记、消费位点这类高频更新的业务状态。状态的特点是写多读少、单条数据小、总量大,而且对实时性要求高。FTS 索引则是从这些状态里抽取文本字段构建的倒排索引,用于关键词搜索。这套体系适合所有从事中间件、状态型存储、索引型检索的研发和运维同学参考。

1. 项目背景与恢复体系设计

1.1 Hermes State DB 的定位和核心痛点

设计 Hermes State DB 时,我最初的思路很简单:底层用带预写日志的持久化 KV 存储,上层定期把状态字段同步给一套独立的全文检索引擎,两边各管各的。状态库负责按主键精确读写,FTS 负责按关键词模糊匹配。拆成两份数据之后,最大的好处是写入路径互不干扰,但坏处也显而易见——故障时你得同时关心两份数据的安全。

运维过这类系统的同学都知道,状态型存储最怕三件事:宕机丢数据、日志写穿磁盘、索引和源数据不一致。前两个属于“主数据完整性”问题,第三个属于“派生数据一致性问题”,它们的恢复方式完全不同。如果只做一套备份,你多半要面对两难:按日志重放,索引还是坏的;直接重建索引,主库的某条状态可能已经丢了。所以从设计一开始,我就把恢复体系拆成了两条独立的线,这就是“双重防线”的由来。

1.2 为什么是“双重防线”而不是单一备份

很多人的第一反应是“我多做几个备份不就完了”。但备份和恢复是两件事。备份解决的是“源数据还在不在”,恢复解决的是“服务能不能按原样回到可用状态”。状态库的恢复目标是数据不丢、顺序正确;FTS 索引的恢复目标则更偏向服务可用、搜索可查、数据可对账。两者判定成功的标准都不一样,用一套方案覆盖两个目标,要么过度设计,要么两头都做不好。

拿我这里实际维护的例子来说。曾经试过把状态库的备份文件直接复制给 FTS 引擎当索引底稿,结果状态备份是某天凌晨两点的快照,索引却是实时的,恢复出来的数据差了整整一天。后来改成只依赖索引自身的持久化,又碰上一次索引存储节点磁盘损坏,连索引带日志一起没了。连续踩了两次坑之后才彻底想明白:状态库的日志只服务于状态库,索引的恢复必须建立在“重新从状态库拉取数据构建”这条独立路径上。谁也不能替代谁。

1.3 两层恢复的边界划分和互相配合

具体落到工程上,我做了这样的事:状态库这一侧,以预写日志和定期快照为恢复源,崩溃后回放日志,把状态恢复到最近一致位点。FTS 索引这一侧,以状态库当前全量为基准做全量重建,再叠加增量变更补齐,最终通过比对和切换上线。两层恢复流程互不依赖,不存在“先恢复 A 才能恢复 B”的强耦合关系。

但这不意味着两层可以完全各搞各的,它们必须共享一套数据校验口径。我在状态库里维护了每一条记录的版本号,FTS 索引里也存了这个版本号。恢复完成后,只需要比对两边记录数和版本号的最大值,就能快速判断数据是否对齐。这个方法很土,但非常有效。后面不管做状态恢复还是索引重建,我都不用再猜自己到底漏了谁。

2. 深入解析状态恢复防线:日志回放与快照配合

2.1 为什么状态恢复必须依赖预写日志

要理解状态恢复,先得说透预写日志的作用。状态库每次写入时,先把变更追加到日志文件,再更新内存态和持久化主文件。这个顺序千万不能反过来。如果先改主文件再写日志,写入过程中宕机就分不清哪些变更已经落盘。如果先写日志再改主文件,崩溃时最多丢失“主文件没来得及更新”的那部分,但日志里已经记录了完整变更,可以回放出来。

生活化类比就是记账:日志相当于流水账本,每一笔都先记下来,主文件相当于总账。总账可能记到一半没写完,但只要流水还在,就能对着流水把账补全。所以判断一份状态数据能不能恢复,核心不是看主文件在不在,而是看日志在不在。我做了个硬性要求:日志和主数据文件必须放在不同磁盘或者至少不同的 IO 路径上,防止磁盘故障把两份一起带走。这个经验是真实付过学费的——有一回日志和主文件在同一块云盘,盘直接只读,恢复方案直接废了一半。

2.2 检查点机制和日志清理周期的参数权衡

日志不能无限增长,否则每写一条状态都要重放全部日志,恢复时间会被拖到不可接受。所以引入了检查点机制:每隔一段时间,把当前内存中的最新状态落盘成一个快照文件,然后清掉该时刻之前的历史日志。恢复时,只需要加载最近一次快照,再重放检查点之后的日志即可,成本可控。

参数配置上,我重点调了两个值:检查点间隔和触发阈值。早期检查点设成每小时一次,结果一小时内日志写了几 GB,恢复要跑半小时。后来改成按日志大小触发:当日志量超过 2GB 或者距上次检查点超过 15 分钟,就主动做一次落盘。这样恢复时日志量基本控制在几百 MB 以内。具体公式很简单,恢复时间约等于日志体积除以重放速率,比如重放速率能做到 50MB/s,1GB 日志就是 20 秒左右。建议所有维护状态库的人,都按“希望恢复时长”反推日志体积阈值,而不是拍脑袋定时间。

注意:检查点不是越频繁越好。每做一次检查点,都要把全量内存态刷一遍磁盘,本身有 IO 开销。如果状态总量很大,频繁落盘会拖慢正常写入。实际配置时我一般把阈值放在“恢复时长可接受”和“日常 IO 开销可接受”这两条线之间的中点。

2.3 状态恢复实操流程与一致性校验

下面给出一套我验证过多次的实操流程。这套流程适用于状态库节点崩溃、能拉起但数据可能残缺的场景。

  1. 停止所有写入流量,避免恢复过程中产生新变更污染现场。
  2. 检查最新快照文件是否存在且完整,缺失则跳过快照直接走全量日志回放。
  3. 加载快照数据到内存,记录快照的日志序列号位置。
  4. 从该序列号位置开始,顺序回放预写日志,逐条更新内存态。
  5. 回放完成后,比对内存中的记录总数和业务侧预期的数量,抽查几条最近更新记录的版本号。
  6. 确认无问题后,开放写入流量,并触发一次新的检查点落盘,缩短下次恢复窗口。

整个过程中最容易出错的环节在第 4 步。日志回放必须是严格顺序的,一旦某条日志损坏,直接中断会丢全部后续变更。我的处理方式是先分离损坏点,跳过单条坏日志并记录下来,恢复完成后由业务侧对账补齐。千万不能因为一条日志坏了就放弃整个回放,那会把可恢复的范围从“丢少量”变成“丢全部”。这一条我在事故复盘时反复强调过。

3. 深入解析 FTS 索引恢复防线:全量重建与增量补齐

3.1 FTS 索引为什么不能直接跟着状态库恢复

FTS 索引在实现上是一套独立的倒排结构:分词结果、词项映射、文档号列表、位置信息,全部是派生数据。它可以通过扫描源数据完整重建,所以不具备和状态库相同的“必须不丢”的语义。既然语义不同,恢复手段就必须独立设计。

最常见的误区是:状态库恢复了,顺手把旧的 FTS 索引文件也拷回去继续用。这看着省事,实际上旧索引文件损坏时你根本不知道它坏在哪。可能是某个分片的倒排列表缺了一段,也可能是词典文件多了几条脏数据。搜索接口不会报错,但返回结果开始莫名其妙变少或者变多,排查起来极其痛苦。所以我把索引恢复的默认策略定成了“能重建就不修复”,从设计上放弃了修补损坏索引这条路。

3.2 全量重建与增量补齐的取舍

索引恢复有两种打法。全量重建:从状态库扫描全部记录,重新构建整棵索引树,耗时取决于数据总量和索引速度。增量补齐:基于某次全量索引快照,只重放快照之后的新增和修改记录,速度快但依赖一个可用的旧索引快照。

如果在故障发生前已经有最近的全量索引快照,并且你知道快照到故障点之间产生了哪些变更,增量补齐是最高效的。但如果索引快照本身已经损坏或过期太久,老老实实全量重建才是唯一可靠选择。我的原则是:索引损坏范围不明时,一律全量重建;明确知道只有部分数据丢失时,才考虑增量补齐。

举一个真实参数。我的状态库里存了大约 800 万条设备记录,单条记录包含设备名、型号、描述等文本字段。全量构建一次索引,单节点跑下来大约需要 40 分钟,索引产物接近 12GB。这个时长在可接受范围内,但如果你有百亿级数据,全量重建可能是小时级甚至天级,那就必须考虑分片并行或者增量补齐方案。实操时我会先按总量测算全量重建耗时,再决定要不要走增量——决策依据永远是“多久能恢复服务”,而不是“哪种方案听起来更高级”。

3.3 重建 FTS 索引的完整操作步骤

按我这里的生产习惯,索引重建流程一般长这样:

  1. 从状态库导出当前全部数据快照,带上版本号字段。
  2. 启动一套独立的“影子索引”构建任务,不占用线上索引的存储和算力。
  3. 构建任务按分片并行处理,每个分片负责一部分数据,完成后合并成完整索引。
  4. 同时订阅状态库的增量变更流,记录从快照时刻开始的每一条新增、更新、删除操作。
  5. 影子索引构建完成后,回放增量变更流,直到追平线上最新位点。
  6. 执行数量校验和抽样校验,比对一致后,将搜索流量灰度切换到新索引。
  7. 观察一段时间,确认无异常后,下线旧索引。

这套流程的关键在于“影子索引”的引入。它让重建过程不影响线上现有索引服务。就算重建过程中又出故障,线上旧索引还能继续扛着读请求(只是数据可能是旧的),不至于直接没有服务可用。灰度切换那一步也很重要,我的经验是先切 5% 流量跑十分钟,确认没有分词报错和查询超时再加到全量,不要一把梭。

注意:增量变更回放一定要包含“删除”操作。很多人重建增量时只关注新增和更新,忽略了删除,结果新索引里残留了大量已失效记录,搜索出来全是脏数据。这个问题我在上线初期踩过,花了整整一个下午才定位到原因。

4. 两条恢复防线的协同与切换策略

4.1 正确恢复顺序:先恢复状态库,再恢复 FTS 索引

如果状态库和 FTS 索引同时处于不可用状态,恢复顺序必须是有讲究的。我的经验是:永远先做状态恢复,再做索引恢复。原因很简单——FTS 索引是依赖状态库生成的,状态库如果没恢复,索引恢复时就拿不到准确的数据源,重建出来也是错的。

实际操作中,我曾遇到过有人自作主张先重建索引,因为“索引构建时间长,可以先跑起来”。结果状态库恢复后,发现大量记录的实际值与索引重建期间读取到的值不一致,最后只能把刚建好的索引丢掉重新来一遍。先恢复状态库看起来让总耗时变长,但保证了整个过程只走一次弯路。如果时间压力特别大,最多做到并行执行——状态恢复的同时,从一份“已知有效的历史快照”提前构建索引底稿,但最终一致性和切换等待必须以状态库恢复完成作为前提。

4.2 数据校验:数量维度与抽样维度双管齐下

两层都恢复完之后,校验是最后一道关口。我目前用的校验方案分为两个维度:

数量维度:比对状态库记录总数和 FTS 索引中的文档总数。正常情况下两者完全一致,不一致就说明索引漏构建或状态库漏恢复。这里要注意删除操作,否则文档数会比记录数多。

抽样维度:随机抽取 1% 的记录,比对每条记录的版本号和关键文本字段在索引中是否一致。版本号不一致说明增量回放没有追平,文本字段不一致直接定位到分词或构建逻辑的差异。抽样比例可以动态调,这个思路可以沿用:先抽 1% 快速扫描一遍,如果没有异常再针对最近 24 小时内变更的记录做全量比对,因为最新的数据最容易出错,历史数据上游已经稳定过很多轮。

4.3 切换策略:灰度发布与快速回滚方案

切换动作看似简单,却是最容易引入新故障的环节。旧索引可能只是数据旧一点,但行为稳定;新索引如果构建时有隐藏问题,全部流量切过去就是事故叠加。所以我的切换策略定为:

先把搜索流量按权重切分,新索引切 5%,运行十分钟,观察错误率和 p99 延迟。如果没有上升,继续切到 25%、50%,最后全量。全量之后再观察 30 分钟,确认无异常才标记切换完成。并且始终保留旧索引随时可以切回的入口,回滚动作必须在一条命令内完成,不能依赖重建。

这套灰度策略的核心价值不是“防止错误发生”,而是“防止错误瞬间影响全部用户”。哪怕新索引延迟高一点、结果少几个,只要没有全量暴露,回滚成本就极低。提醒一句:切流量之前务必确认新索引对应的数据版本已经追平,否则会出现新旧索引返回结果不一致混着的现象,那比搜索不可用更让人头大。

5. 常见问题与排查技巧实录

5.1 高频故障速查表

故障现象可能原因排查要点处理建议
状态库能启动但部分数据缺失预写日志尾部损坏查看日志回放是否跳过坏记录跳过损坏点,业务对账补数据
FTS 搜索返回正常但结果偏少增量回放漏了删除操作比对文档总数与状态库记录数重新全量对齐,修复增量逻辑
索引重建频繁失败构建任务与写入流量争抢资源观察 IO 和 CPU 争用情况构建任务限流或错峰执行
切换新索引后查询超时新索引未经预热,内存缓存为空检查缓存命中率和慢查询日志先灰度预热一段再切全量
状态恢复后 FTS 数据对不上状态库恢复未完全追平日志比对两边最大版本号重新回放增量变更流

5.2 三个典型故障现场的复盘记录

这里分享三个真实处理过的故障现场,给读者一些具体观感。

第一起是索引分片文件损坏。现象是搜索不到最近一周的新设备,但旧数据正常。排查发现索引库某分片的倒排文件在磁盘层出现静默损坏,不再具有可读性。由于该分片数据量不大,我直接对该分片执行局部全量重建,再合并回主索引,整个过程约 8 分钟,业务无感知。这个案例的核心启发是:索引恢复不必永远全量,分片级操作在定位明确时效率极高。

第二起是状态库和 FTS 索引版本号严重错位。现象是搜索能返回记录,但记录详情里的状态和索引里的文本对不上。排查后确认是增量变更通道在某个时段出现了积压,重建索引超过了变更回溯窗口,导致大量变更没有进入索引。最后我把变更积压清空,等待增量追平后再做抽样校验,数据对齐后放行。这个案例提醒我:增量消费积压是索引不一致的头号原因,监控必须盯消费延迟而不是只看消费进程是否存活。

第三起是最严重的一次全故障。状态库所在存储节点宕机,日志文件所在磁盘同时掉线,FTS 索引依赖同一底层基础设施全部不可用。最终处理方式是:从远端备份拉取最新快照,回放备份点之后的日志副本,恢复状态库;清洗掉原索引,从恢复好的状态库重新全量构建索引。整个过程耗时接近三小时。这个案例说明了异地冗余的必要性——同一个机房、同一个磁盘阵列里的“双份数据”,在物理故障面前等于一份。这是我花了大代价换来的经验。

5.3 避坑技巧与日常防护建议

以下几件事是我吃了亏之后才固化下来的,直接分享出来:

  • FTS 索引的持久化数据至少要保留一份不用作线上服务的冷备副本,且放置在与线上存储完全隔离的路径上。
  • 状态库的预写日志必须监控落后量,日志写入延迟超过阈值时要及时告警,这往往是磁盘故障的前兆。
  • 增量回放逻辑里必须显式处理删除事件,不能只关注新增和更新。
  • 每次索引重建前,先把预期的文档总数打印出来,重建完成后自动比对,任何不一致直接中断流程,而不是带着问题上线。
  • 日常定期做恢复演练。我按季度安排一次完整的“状态库 + FTS 索引同时故障”演练,演练不打印“成功”就算结束,必须记录恢复时长、误差值、手工干预步骤,逐项改进。

说到演练,我有个挺实在的心得:不要拿测试环境的小数据量演练,一定要压到接近生产数据量的规模。小数据量恢复成功没有参考意义,很多问题都是数据量上来之后才暴露的,比如全量构建的 OOM、日志回放速度骤降。我现在的习惯是在每个季度末,用生产数据脱敏后的副本,在独立环境跑一遍双重防线恢复流程,记录基线数据,再对比下个季度的表现,这样恢复能力退步可以第一时间被发现。日常维护 FTS 索引的同学也可以把这个方法论复制过去,它不依赖具体技术栈,任何带状态存储和全文检索的系统都适用。

相关新闻

双重防线:FTS索引与State DB的恢复实战指南

双重防线:FTS索引与State DB的恢复实战指南

凌晨两点半,某即时通信平台的核心服务在发布过程中被强制重启,启动日志里赫然写着“recovery completed”,所有人都松了口气。结果一个小时后业务方找过来:几个小时前的关键词检索查不到结果,部分消费者的消费位点凭空…

2026/10/20 6:52:44 阅读更多 →
阿里云AI算力硬件体系深度解析:GPU选型、RDMA互联与系统级调优

阿里云AI算力硬件体系深度解析:GPU选型、RDMA互联与系统级调优

1. 这不是“云厂商宣传稿”,而是一份算力硬件工程师的现场笔记“一文看懂阿里云AI算力硬件体系”——这个标题在技术社区里出现频率很高,但多数内容要么是PPT式罗列型号参数,要么是营销口径的“性能提升XX%”,真正能讲清楚“为什么…

2026/10/20 6:52:44 阅读更多 →
十大AI论文工具测评:从文献综述到定稿的实战指南

十大AI论文工具测评:从文献综述到定稿的实战指南

凌晨三点半,我收到一位学弟的消息:“文献综述又被导师打回来了,说写得像‘综述生成器’跑出来的。怎么办?”这个场景太常见了。2026年聊到研究生毕业论文写作,已经绕不开AI工具这个话题。它们确实能显著提速&#xff0…

2026/10/20 6:51:43 阅读更多 →

最新新闻

Abaqus隧道空洞模拟:地表沉降有限元分析建模方法与工程应用

Abaqus隧道空洞模拟:地表沉降有限元分析建模方法与工程应用

从实际项目出发,我接到过一个很有意思的模拟任务:用Abaqus分析隧道施工中形成的空洞对地表沉降的影响规律。这类问题在岩土工程里特别典型——城市地下管线破损、盾构注浆不密实、矿山采空区塌落,都会在地层内部留下空洞,而地表沉…

2026/10/20 7:38:07 阅读更多 →
轻量级Coding Agent设计:如何通过架构减法节省58.7% Token

轻量级Coding Agent设计:如何通过架构减法节省58.7% Token

1. 项目概述:一个轻量级 Coding Agent 的诞生逻辑“我做了一个 Coding Agent,结果比 Claude Code 少用了 58.7% Token”——这句话刚在技术社区刷屏时,我第一反应不是惊讶,而是立刻点开原文代码仓库,翻看它的 prompt 结…

2026/10/20 7:38:07 阅读更多 →
用APIKit与Param Miner挖掘隐藏API端点:Burp Suite主动探测实战指南

用APIKit与Param Miner挖掘隐藏API端点:Burp Suite主动探测实战指南

先问个扎心的问题:做接口测试或者安全评估的时候,你是不是还停留在“开Burp、挂代理、点开HTTP History看请求”这个阶段?如果是,那我要说一句可能不太中听的话——你手里的Burp Suite,至少有一半的潜力被你浪费了。经…

2026/10/20 7:38:07 阅读更多 →
MIL-C-5015军规连接器振动加速度传感器:选型安装与排查

MIL-C-5015军规连接器振动加速度传感器:选型安装与排查

干设备状态监测好些年,有一类传感器是小众但特别关键的——带军规连接器的振动加速度传感器。光看名字“MIL-C-5015振动加速度传感器5/8-24UNF军标连接器”就够劝退了,但如果你在航空发动机试车台、燃气轮机厂房、重型机械现场转过一圈,一定会…

2026/10/20 7:38:07 阅读更多 →
杰理平台time PWM实战:定时器比较输出的配置与踩坑指南

杰理平台time PWM实战:定时器比较输出的配置与踩坑指南

前阵子帮朋友调一块杰理平台的小板子,现象很蹊跷:按键控制LED亮度时,IO口确实有电平变化,但用示波器一看,波形完全不是PWM该有的样子,反而是一串不规则的脉冲,频率还飘。翻遍SDK里的例程&#x…

2026/10/20 7:38:07 阅读更多 →
纯.NET自绘打印模板设计器:拖拽式可视化与动态渲染

纯.NET自绘打印模板设计器:拖拽式可视化与动态渲染

简介:这是一套面向.NET开发者的C#可视化打印模板设计源码,纯.NET实现、不依赖任何第三方控件,适合需要为发票、报告、证书、标签及单据类业务快速搭建打印能力的初中级工程师。资源提供模板编辑器、图形设计工具与布局管理器等组件&#xff0…

2026/10/20 7:37:06 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →