ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Open Library 基于 OL Dump 的 Solr 全量重建索引实战指南:solr_builder 流水线解析

Open Library 基于 OL Dump 的 Solr 全量重建索引实战指南:solr_builder 流水线解析 后端前端搜索引擎【免费下载链接】openlibraryOne webpage for every book ever published!项目地址https://gitcode.com/gh_mirrors/op/openlibrary点击查看免费下载本指南以 scripts/solr_builder/README.md 为核心骨架结合仓库内 Jenkinsfile、compose.yaml、solr_builder.py 等实现完整讲解如何从 openlibrary.org 的公开数据 Dump 出发经 Postgres 本地副本、并行索引、Solr 优化、生产部署最终构建出一个全新的 Open Library 搜索索引。读完本文你将掌握 solr_builder 这套重索引流水线的每个环节如何搭建 Jenkins 编排环境、如何理解与调优 Pipeline 参数、如何排查经典故障以及如何把重建好的 Solr 数据安全部署回生产服务器。1. solr_builder 是什么一条从 Dump 到线上索引的完整流水线solr_builder位于仓库 scripts/solr_builder 目录它的目标非常明确用 Open Library 官方发布的全量数据 Dump重新构建一个可用的 Solr 实例。README 明确指出这套流程只在 OJF 环境上做过测试属于生产级运维流程而非一般开发者的一键脚本。从目录结构可以看出它覆盖了全链路所需的全部件组成路径作用CI 编排scripts/solr_builder/Jenkinsfile定义整条重索引流水线及全部构建参数容器编排scripts/solr_builder/compose.yaml定义 db / adminer / solr / solr_prod / ol 五类服务核心索引代码scripts/solr_builder/solr_builder/solr_builder.py数据提供、分块查询、写入 Solr 的主程序主题索引scripts/solr_builder/solr_builder/index_subjects.py通过 Solr facet 生成 subject/person/place/time 文档SQL 脚本scripts/solr_builder/sql建表、建索引、统计、部分导入等辅助 SQL运维脚本dump-solr.sh、restore-solr.sh、deploy-solr-next.sh生产 Solr 的打包、恢复与切换辅助工具aliases.sh、utils.sh、index-type.sh、psql-import-simple.sh常用 shell 封装整体思路可以概括为三步先把 Dump 灌进本地 Postgres再以并行分块的方式从 Postgres 读取数据写入 Solr最后对 Solr 做 optimize 并部署上线。2. 架构总览Jenkins 控制台 三组容器的协作solr_builder的流水线由 Jenkins 驱动但它真正干活的是 scripts/solr_builder/compose.yaml 里定义的五类服务服务镜像职责关键配置dbpostgres存放 Dump 导入后的本地数据副本POSTGRES_PASSWORD: example挂载postgres-data卷admineradminerPostgres 的可视化管理界面端口映射8087:8080solrsolr:10.0.0批量索引的目标 Solr 实例关闭自动软提交command: solr-precreate openlibrary ...solr_prodsolr:10.0.0用于接入生产/测试环境的 Solr独立 profile生产级内存与提交参数ololpython:latest本地构建运行 Open Library 索引代码的执行容器绑定挂载仓库根目录、连接 db 与 solr 网络需要特别注意的是Solr 的 JVM 参数针对批量加载做了专门调优见 compose.yaml- SOLR_OPTS -Dsolr.autoSoftCommit.maxTime-1 # 完全关闭软提交减少大批量写入开销 -Dsolr.autoCommit.maxTime3600000 # 硬提交间隔放大到 1 小时 -Dsolr.environmenttest而solr_prod则使用与生产一致的参数软提交 60s、硬提交 120s、-Dsolr.max.booleanClauses30000、SOLR_JAVA_MEM-Xms10g -Xmx10g并声明-Dol.replication.role.leadertrue使其可以作为生产 Solr 的副本源。两个 Solr 服务共享solr-data卷与 conf/solr 配置集solr_precreate openlibrary会用该配置集预创建名为openlibrary的 core。2.1 关于 Docker socket 转发的关键注意事项README 专门强调了一个容易误解的点虽然表面上看起来是Jenkins Docker 镜像 → 构建 Docker 镜像 → 启动 solr_builder Docker 镜像的层层嵌套由于把宿主的/var/run/docker.sock转发进了 Jenkins 容器实际上所有容器操作都发生在宿主机 Docker 上这也是业界推荐的 docker-in-docker 替代方案。Jenkinsfile 中的args -v /var/run/docker.sock:/var/run/docker.sock就是这一机制的直接体现。由此带来两个必须接受的限制不要假设自己对宿主容器有完全控制权——操作不慎可能停掉无关容器不要同时跑多个重索引任务——当前 Pipeline 对容器名、卷名等做了强假设并发必然出错。3. 第一步启动 Jenkins 控制台README 给出了启动 JenkinsBlue Ocean 版的完整命令参数含义如下docker run \ -u root \ # 以 root 运行便于操作 docker socket -d \ -p 8080:8080 \ # Jenkins Web UI -p 50000:50000 \ # Jenkins 与构建代理通信的端口 -v jenkins-data:/var/jenkins_home \ # Jenkins 数据卷持久化配置/构建记录 -v /storage:/storage \ # 挂载宿主存储用于存放 OL dump 文件 -v /var/run/docker.sock:/var/run/docker.sock \ # 转发 docker socket -v /var/lib/docker/volumes/jenkins-data:/var/lib/docker/volumes/jenkins-data \ --restart always \ --name jenkins \ jenkinsci/blueocean后续步骤按 Jenkins 官方 setup wizard 完成初始化配置创建一个Pipeline 项目Source Control Management 选择 Git 指向本仓库务必把 Script Path 设置为scripts/solr_builder/Jenkinsfile即本目录下的 Jenkinsfile而不是仓库根目录默认的 Jenkinsfile运行 Pipeline。关于 Jenkins 日志与产物任务结束后日志会以 artifact 形式保存也可以在经典 UI 中进入workspace目录查看 logs 子目录README 提示可忽略路径中包含的目录。4. Jenkinsfile 构建参数一览Jenkinsfile 通过parameters块暴露了全部可调开关理解它们是使用这套流水线的前提参数类型/默认值含义WIPE_OLD_POSTGRESboolean /false为 true 时删除现有 Postgres 并重新灌 Dump否则假定 Postgres 已有数据WIPE_OLD_SOLRboolean /false为 true 时删除现有 Solr 卷从空索引开始INDEX_WORKSboolean /true是否重建 works作品索引INDEX_ORPHANSboolean /true是否重建 orphans未挂到任何 work 下的 editionINDEX_SUBJECTSboolean /true是否重建 subjects含 person/place/time 四类主题INDEX_AUTHORSboolean /true是否重建 authors作者索引INDEX_LISTSboolean /true是否重建 lists书单索引MAX_CORESstring /18最大并行核数控制并发索引实例数量PIP_INDEX_URLstring /自定义 PIP 源生产环境需要HTTPS_PROXYstring /HTTP 代理生产环境需要NO_PROXYstring /archive.org,openlibrary.org,.archive.org,.openlibrary.org不走代理的域名列表environment块还推导了几个关键路径DUMP_DIR/storage/openlibrary存放所有 Dump 文件HOST_SOLR_BUILDER_DIR通过docker volume inspect获取jenkins-data卷的宿主挂载点从而把 Jenkins 工作区路径换算成宿主机路径保证 docker-in-docker 场景下卷挂载正确。5. 流水线核心阶段源码解析5.1 Stage 1在本地 Postgres 中重建数据库副本该阶段仅在WIPE_OLD_POSTGREStrue时执行依次完成1清理并启动数据库容器删除旧的solr_builder-db-1、solr_builder-adminer-1容器与solr_builder_postgres-data卷然后docker compose up -d --no-deps db拉起 Postgresadminer 是可选 GUI端口 8087等待 10 秒后用 create-dump-table.sql 建表。该 SQL 定义了四张核心表testType/Key/Revision/LastModified/JSON 的通用实体表JSON 为 jsonb、ratings、reading_log、cover。2下载 Dump 文件从 openlibrary.org 与 archive.org 下载五类数据链接定义于 JenkinsfileDump来源ol_dump_latest.txt.gzhttps://openlibrary.org/data/ol_dump_latest.txt.gzol_dump_ratings_latest.txt.gzhttps://openlibrary.org/data/ol_dump_ratings_latest.txt.gzol_dump_reading-log_latest.txt.gzhttps://openlibrary.org/data/ol_dump_reading-log_latest.txt.gzol_dump_covers_metadata_latest.txt.gzhttps://openlibrary.org/data/ol_dump_covers_metadata_latest.txt.gzosp_totals.dbarchive.org 上的 Open Syllabus 计数README 提示需与ol-solr-updater-start和 Makefile 保持同步文件名的日期后缀如ol_dump_2021-09-13.txt.gz通过 curl 跟随重定向获取url_effective自动解析下载用wget --trust-server-names --no-clobber且会在下载新 Dump 前清理掉旧版本文件。3导入 Dump 并校验核心导入由 psql-import-simple.sh 完成——解压后先用sed s/\\u0000//g剔除 NUL 字符否则 Postgres COPY 会报错再通过COPY ... FROM STDIN with delimiter E\t escape \ quote E\b FREEZE csv快速灌入指定表FREEZE选项可以大幅提升大批量 COPY 的性能。四个 Dump 分别导入test、ratings、reading_log、cover表。导入结束后有一个自动一致性校验比较 Dump 文件解压后的行数zcat ... | wc -l与数据库表行数count-all-rows.sql 的SELECT count(*) FROM test二者不相等则直接断言失败。随后执行 create-indices.sql 创建索引批处理场景下先灌数据后建索引通常比逐行插入快得多。5.2 Stage 2并行填充 Solr进入 Stage 2 时若WIPE_OLD_SOLRtrue会先停掉并删除solr_builder-solr-1、solr_builder-solr_prod-1容器和solr_builder_solr-data卷。随后启动 Solr、手动拉取openlibrary/olbase:latest镜像、构建ol服务镜像并编译 Cython 文件见 setup.py用cythonize把solr_builder.py编译为扩展模块以提升性能。接着进入并行的五路 Reindexing各自的执行方式略有不同works / orphans / authors / lists由 index-type.sh 驱动例如./index-type.sh work ${MAX_CORES} workssubjects直接调用 index_subjects.py对subject/person/place/time四种类型分别以--chunk-size 10000分块执行。index-type.sh 的并行分块机制是这套方案性能的关键脚本维护一个运行中 runner 数上限INSTANCES即MAX_CORES循环里先通过solr_builder.py fetch-end拿到下一块的结束 key以--start-at /$next_start从上次断点继续而不是用OFFSET——solr_builder.py 的build_job_query中注释明确说明 start_at 方式比 offset 高效得多因为 offset 需要遍历全部前面的行然后以--limit $CHUNK_SIZE默认 10000启动一个后台 runner 写入该块。为了不让所有 runner 同时抢内存脚本按CHUNK_ETA / INSTANCES秒错峰启动最后再等待残留 runner 全部收尾。CHUNK_ETA可通过环境变量覆盖works 阶段 Jenkinsfile 设为 70orphans 设为 35。solr_builder.py 的数据链路核心实现 scripts/solr_builder/solr_builder/solr_builder.pyLocalPostgresDataProvider继承自 Open Library 的DataProvider通过 postgres.ini[postgres]段hostdb、密码 example连接本地 Postgres用query_batched以命名服务端游标按每批 1000 行流式取数对每批 key按 job 类型预缓存关联数据works 要缓存其 editions、editions 的 IAInternet Archiveocaid 元数据、前五位作者、ratings 聚合与 reading log 聚合见cache_work_editions/cache_work_authors/cache_work_ratings/cache_work_reading_logsorphans 则缓存 edition 的 ocaid 与作者lists 与 authors 无需额外缓存最终调用openlibrary.solr.update.update_keyscommitFalse、skip_id_checkTrue把文档批量写入 SolrPLog进度记录器会按固定字段seen/total/percent/elapsed/q_1/q_auth/q_ia/cached/ia_cache/next写入 progress 文件。每个索引阶段结束后会调用solr_commit()curl http://localhost:8983/solr/openlibrary/update?committrue并把各 runner 的进度文件与日志分别聚合压缩为works-progress.txt.gz、works-indexing.log.gz等 artifact 归档tail -q -n1 ... | gzip/cat ... | gzip。index_subjects.py 的特殊之处subjects 不需要从 Postgres 读数据而是直接对 Solr 发起type:work的 facet 查询facet.fieldsubject_facet/person_facet/place_facet/time_facet、facet.sortindex、facet.mincount1把 facet 项转成type:subject的文档写回 Solrindex_all_subjects用asyncio维护最多instances个并发 worker一个 worker 返回结果数小于chunk_size即判定遍历完成。5.3 Stage 3Optimize 索引全部写入完成后执行docker compose exec -T solr curl -s http://localhost:8983/solr/openlibrary/update?optimizetruemaxSegments1Jenkinsfile 注释形容 optimize 类似于磁盘整理但大批量导入后是必须的——它会合并 Lucene 段maxSegments1强制归并为单段大幅改善后续查询性能对日常增量写入则不需要频繁执行。6. 常见故障排查来自 README 的实战经验6.1 SCM 字段为空 / 没有选项按官方 Defining a Pipeline in SCM 流程Pipeline 的 Definition 应选Pipeline script from SCM随后点开 SCM 字段选择 Git——但该字段可能显示空白。解决方法在页面顶部的 alerts 区域更新并重启 Jenkins该问题通常源于插件未完全就绪。6.2 构建几乎立刻失败Invalid agent type dockerfile控制台报错特征org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: WorkflowScript: 3: Invalid agent type dockerfile specified. Must be one of [any, label, none] line 3, column 5. dockerfile { ^原因缺少Docker与Docker Pipeline两个插件。解决Dashboard Manage Jenkins Manage Plugins Available plugins搜索 docker安装Docker可能显示为 Docker plugin与Docker Pipeline。6.3 java.lang.NoSuchMethodError: SandboxTransformer.mightBePositionalArgumentConstructor报错特征java.lang.NoSuchMethodError: boolean org.kohsuke.groovy.sandbox.SandboxTransformer.mightBePositionalArgumentConstructor(org.codehaus.groovy.ast.expr.VariableExpression) at com.cloudbees.groovy.cps.SandboxCpsTransformer.visitAssignmentOrCast(SandboxCpsTransformer.java:93)原因Groovy Pipeline 插件版本过旧与当前 Jenkins/Groovy 沙箱不兼容。解决Dashboard Manage Jenkins Manage Plugins Installed plugins搜索 Groovy Pipeline 并更新到最新版。7. 修改与调试 Pipeline 的三种姿势README 提供了两套开发迭代方式本地路径模式把 Jenkins 项目指向本地路径但必须重启 Jenkins 并挂载该路径例如启动命令中追加-v $HOME:/home否则 Jenkins 容器内看不到宿主目录Fork 分支模式把 Git URL 改为自己的 fork并指定开发分支如*/solr-builder--jenkins每次修改后 push 到该分支再运行项目即可测试——Jenkins 每次运行都会从分支拉取最新代码。编辑建议README 推荐用VS Code 编写 Pipeline有声明式 Pipeline 校验扩展通用开发技巧参考 Jenkins 官方 Pipeline development 文档本仓库的 Jenkinsfile 本身也是很好的语法范本含when { expression }条件执行、parallel并行阶段、post { always }收尾、void solr_commit()函数定义等声明式语法要素。8. Deploy把重建的索引部署到生产索引在 solr_builder 服务器上构建完成后README 给出了完整的部署链路三台机器协作solrbuilder 服务器负责打包ol-solr0 生产服务器负责恢复ol-home0 负责增量追平。8.1 在 solrbuilder 服务器上打包 Solr 数据time docker run --rm \ --volumes-from solr_builder_solr-1 \ -v /tmp/solr:/backup \ ubuntu:xenial \ tar czf /backup/solrbuilder-$(date %Y-%m-%d).tar.gz /var/solr/dataREADME 记录的历史耗时2020-10 的 Dump 约 41 分钟、产物约 14GOJF 环境可据此预估磁盘与时间成本。注意卷名solr_builder_solr-1对应docker compose自动生成的容器名。8.2 在生产服务器上拷贝并恢复cd /opt/openlibrary # 从 solrbuilder 服务器拷贝README 记录 2020-11-05 实测约 4 分钟 time scp YOUSOLR_BUILDER_SERVER:/tmp/solr/solrbuilder-2020-03-02.tar.gz /tmp/solr/solrbuilder-2020-03-02.tar.gz # 恢复到 Solr 数据卷README 记录 2021-08-11 实测约 7 分钟 time docker run -v openlibrary_solr-data:/var/solr/data -v /tmp/solr:/backup ubuntu:xenial \ tar xzf /backup/solrbuilder-2021-08-11.tar.gz # 启动服务 COMPOSE_FILEcompose.yaml:compose.production.yaml HOSTNAME$HOSTNAME docker compose --profileol-solr0 up -dREADME 特别强调卷名的命名规则openlibrary_solr-data{OL_DIR}_{SOLR_DATA_VOLUME}——OL_DIR是仓库所在目录名通常即openlibrarySOLR_DATA_VOLUME是 compose.yaml 中 Solr 服务使用的数据卷名。若命名不匹配恢复命令会静默写入一个错误的新卷导致线上 Solr 仍是旧数据。8.3 更完整的生产运维脚本README 的手动命令之外仓库还提供了三份更高层次的自动化脚本README 的 Deploy 章节对应的正是这套流程dump-solr.sh在指定 Solr 服务器上生成 tar 包——先检查磁盘空间比较/var/solr大小与/tmp空闲空间、提交残留变更、docker pause暂停 Solr 后离线打包、恢复运行再通过ia工具上传到 Internet Archiveol_solr_dumpitem附带 offset 文件以便后续增量追平restore-solr.sh从 IA 下载 dump 与 offsetdocker system prune -f --all --volumes清理生产环境包含删除 Solr 数据卷用ubuntu:bionic容器解包到openlibrary_solr-data卷重启服务并把 offset 写回 solr-updater最后sed -i s/--no-solr-next/--solr-next/切换增量更新逻辑deploy-solr-next.sh完整的新 Solr 转正编排——依次切换全部 web 节点到新 Solr 并验证搜索、dump 旧 Solr 作为备份、恢复新数据、逐节点回切全程通过 utils.sh 中的 Slack 通知与test_all_ol_search健康检查对ol-web{0..3}:8080、openlibrary.org、testing/staging.openlibrary.org发起search.json?qhello并断言numFound非 0。9. Resetting重跑前必须清理的容器与卷由于 Pipeline 对容器名和卷名做了强假设重跑任务前必须手动清理上一轮产物。README 给出的清理命令分两组# new solr 容器/卷 docker rm -f -v solr_builder_solr-1 docker volume rm solr_builder_solr-data # DB 容器/卷 docker rm -f -v solr_builder_db-1 solr_builder_adminer-1 docker volume rm solr_builder_postgres-data注意 README 中的容器名solr_builder_solr-1与新版 compose 命名如 Jenkinsfile 中出现的solr_builder-solr-1存在横杠/下划线差异实际清理时应以当前docker compose ps显示的容器名为准Jenkinsfile 内对应阶段Wipe old postgres/Wipe old solr使用的是docker rm -f -v ... || true的容错写法并把post { unsuccessful }中的清理逻辑置于失败后自动执行。10. 已知边界与待办Final SyncREADME 在 Final Sync 一节明确标注为TODO即本文第 8 节部署链路之后的最后一步尚待完善思路是向 compose.production.yaml 中添加一个指向新服务器的 solr-updater并将其 offset 设置为正确的日期可参考 Open Library 仓库 issue #5493 Move production solr from solr1 to solr0 的讨论线索。实际部署时可参考 deploy-solr-next.sh 第 91-100 行的sed切换逻辑理解恢复数据 设置 offset 切换增量更新三件事的组合关系。同时需要牢记本流程的适用前提README 声明这套重索引仅在 OJF 环境验证过其中记录的各项耗时打包 41 分钟/14G、scp 4 分钟、恢复 7 分钟等均为特定时期的历史观测值会随 Dump 体积与硬件环境显著变化生产环境使用还需正确设置PIP_INDEX_URL、HTTPS_PROXY、NO_PROXY三个参数Jenkinsfile 中注明生产环境需要。在动手前建议先通读 Jenkinsfile 与 compose.yaml 两份编排文件再参照本指南逐阶段执行即可获得一条从 OL Dump 到生产 Solr 的完整、可控的重索引链路。赞分享后端前端搜索引擎【免费下载链接】openlibraryOne webpage for every book ever published!项目地址https://gitcode.com/gh_mirrors/op/openlibrary点击查看免费下载相关推荐LLM Zoomcamp 2024 模块 5 实战用 Mage 编排 Elasticsearch 构建全量重建的 RAG 索引流水线LLM Zoomcamp 2024 模块 5 实战用 Mage 编排 Elasticsearch 构建全量重建的 RAG 索引流水线 本文基于 LLM Z示例工程教程人工智能大模型Taskgo-task3.x 版本演进全解析从 CHANGELOG 看现代任务运行器的核心能力Taskgo task3.x 版本演进全解析从 CHANGELOG 看现代任务运行器的核心能力 导读 本文以当前仓库的 CHANGELOG.md http后端前端搜索引擎DrFact 知识库索引与推理流水线实战基于 LAUNCH.md 的完整部署指南DrFact 知识库索引与推理流水线实战基于 LAUNCH.md 的完整部署指南 DrFactA Differentiable Fact Centric A人工智能深度学习NLP计算机视觉强化学习上一篇显卡变砖进不了系统怎么办NvidiaOverclocking应急修复开机循环自救DDU/NVCleanstall驱动清理下一篇bee升级指南版本迁移与兼容性处理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表