解释“$text”全文索引与“_fti”端点在实现层面的差异。

解读

国内面试官问这道题,并不是想听你背文档,而是想看你是否真的在生产环境“踩过坑”。
“$text”是 CouchDB 3.x 之后官方内置的 Mango 全文索引,走的是 CouchDB 自己维护的 ICU 分词 + 倒排索引
“_fti”则是 老版本 1.x/2.x 时代依赖外部 Cloudant-Lucene 插件 的遗留接口,本质上是把文档同步到 Lucene 索引目录,再通过 独立 Java 进程 提供搜索。
一句话:前者是“官方亲儿子”,后者是“历史干儿子”。能否把两者在 索引生命周期、查询语法、事务一致性、运维成本 四个维度拆开讲,是得分关键。

知识点

  1. 索引存储位置

    • $text:与主库同机,index 文件落在 .couch 目录下的 _text_idx 子目录,由 couch_index_server 统一管理,随 shard 一起分片、一起复制
    • _fti:必须额外部署 cloudant-lucene 服务,索引文件放在 lucene-data/ 目录,不参与 CouchDB 内部分片复制,需要你自己做 NFS 或 DRBD 保证高可用。
  2. 触发机制

    • $text:文档写入后,由 couch_index_updater 进程异步消费 seq_tree,更新倒排索引,同一事务内保证一致性视图
    • _fti:CouchDB 通过 httpdb 钩子 把文档 POST 到 lucene 监听端口(默认 5985),跨进程、跨网络,失败就丢消息,需要手工补偿重建
  3. 查询语法

    • text:在 Mango 里用 **{"text": "北京 天气"}**,支持 ICU 中文分词、布尔逻辑、短语匹配,返回结果天然带 {"$rank": score} 字段。
    • _fti:走 /_fti/local/{ddoc} 端点,参数是 ?q=北京 AND 天气,语法是 Lucene QueryParser,中文需要提前 IK 或 Jieba 插件,否则只能单字切。
  4. 性能与调优

    • $text:索引段与 CouchDB 的 IO 队列合并不需要额外 JVM 内存;但大库首次构建会 抢磁盘 IOPS,建议 低峰期触发
    • _fti:独立 JVM,堆内存要单独调热点分片容易造成 lucene 节点 OOM;国内云主机 4C8G 场景下,单次 merge 会飙到 200% CPU,必须 cgroup 限流
  5. 运维与监控

    • $text:直接 /_node/_local/_stats/couchdb/httpd/text_search 看延迟;索引损坏时只需 删除 _text_idx 目录重建自动从 0 开始顺序扫描
    • _fti:需要 JMX + Prometheus jmx_exporter 才能看 lucene 指标;索引 corruption 后只能 停 lucene、删目录、全量重建TB 级库重建一次 6~8 小时, SLA 血崩。
  6. 国产化合规

    • $text:ICU 分词库已 内置在 CouchDB 主包不依赖外部服务信创环境可直接通过麒麟 V10 适配
    • _fti:cloudant-lucene 依赖 OpenJDK + Apache Lucene 8.x信创名录里无 Lucene 8需要降级到 7.x 并重新编译甲方验收会被挑刺

答案

text”是CouchDB3.x官方内建的全文索引,索引文件与主数据同机同分片Erlang进程异步维护查询走MangoDSL中文ICU分词开箱即用运维成本低、国产化合规fti”是早期依赖外部cloudantlucene插件的遗留方案,索引落在独立JVM进程不参与CouchDB复制查询用LuceneQueryParser中文需额外插件运维复杂、重建慢、信创适配难。生产环境新集群应优先使用text”是 CouchDB 3.x 官方内建的全文索引,**索引文件与主数据同机同分片**,**由 Erlang 进程异步维护**,**查询走 Mango DSL**,**中文 ICU 分词开箱即用**,**运维成本低、国产化合规**; “_fti”是早期依赖 **外部 cloudant-lucene 插件** 的遗留方案,**索引落在独立 JVM 进程**,**不参与 CouchDB 复制**,**查询用 Lucene QueryParser**,**中文需额外插件**,**运维复杂、重建慢、信创适配难**。 生产环境新集群应 **优先使用 text**,_fti 只出现在历史系统改造场景,且必须 加消息队列补偿 + 双读开关 保证平滑下线。

拓展思考

  1. 如果甲方要求 “lucene 语法兼容性”,又不想维护 _fti,你可以 **在 text之上封装一层查询翻译服务:把luceneq参数解析成Mangotext 之上封装一层查询翻译服务**:把 lucene q 参数解析成 Mango text 语法,用 Node-RED 或 Go 网关实现两周可上线
  2. 当单库 >2 亿条、索引目录 >500 GB 时,$text 的 首次构建时间可能超过 6 小时,此时可 临时关闭 search_enabled先让业务跑冷数据再灰度开启_fti 在这种体量下基本不可维护
  3. 国内金融客户常问 “全文索引是否影响 point-in-time 备份”——$text 因为 与主 shard 共享一致性快照备份恢复后索引自动复用;而 _fti 独立目录必须额外做 lucene 目录的 fsync + tar否则恢复后搜索直接为空审计过不了