系统设计 Lab
Job Board 先用 PostgreSQL 完成全文检索与结构化过滤;只有候选打分、搜索功能或独立扩容成为主导约束时,Search Service 才成为单独的 component。
调节 active jobs、搜索 QPS、可复用 query 的实测 cache hit、keyword candidates、职位更新率与 freshness 预算。观察 PostgreSQL 何时足够、热门结果或 search session 何时值得 cache,以及 Elasticsearch / OpenSearch 何时才应成为独立 component。
分步讲解
一步一步把它想清楚
要点
常规演进场景
从左到右点击,就是预设的演示路径。每张卡片都会改变 workload 输入。
推荐形态
瓶颈
为什么会变
决策权衡
有出处支撑的规则
这些是模型背后那些经得起时间考验的 system design 论断。而 slider 的具体阈值,则被刻意标注为教学用的假设。
GIN 是 PostgreSQL 全文搜索的首选 index type
GIN 保存 lexeme 到 rows 的倒排关系,适合先做 keyword candidate retrieval;动态 relevance 仍由 ts_rank / ts_rank_cd 计算。
PostgreSQL — Preferred Index Types for Text SearchPartial index 只保存满足 predicate 的 rows
active-only GIN、B-tree 和 GiST 可以排除多年 closed history,但 query predicate 必须能明确推出 index predicate。
PostgreSQL — Partial IndexesOpenSearch keyword search 默认使用 BM25
专用 Search Service 把全文 relevance、non-scoring filters 和 Top-K retrieval 当作核心 workload,而不是关系数据库中的附加能力。
OpenSearch — Keyword searchElasticsearch 默认不会 cache 带 hits 的完整搜索结果
Shard request cache 默认只 cache size=0 的 totals、aggregations 和 suggestions;热门 Top 20 result 需要 Search API 明确使用 Redis 一类的外部 cache。
Elasticsearch — Shard request cacheCDC 捕获数据库已经提交的 row-level changes
CDC 是 change capture mechanism:connector 读取数据库 transaction log 并产生 change-event stream。Queue 是可选的传输与缓冲层,Indexer 才负责更新 SearchDocument。
Debezium — CDC ArchitectureOutbox 让业务状态与 event 在同一个 transaction 提交
Job API 同时写 Job row 与 outbox row;CDC connector 再捕获 outbox change。这样避免 PostgreSQL 成功、消息发送失败造成的同步双写分叉。
Debezium — Outbox Event Router独立 Search Index 是 near real-time,不是事务内立即可见
document changes 经过 refresh 才进入可搜索 segments;所以搜索 freshness 与 Application API 的业务正确性必须分开。
Elasticsearch — Near real-time search教学用假设
- 候选数、latency 和 throughput 公式只是展示拐点的保守教学模型,不是 PostgreSQL、Elasticsearch 或 OpenSearch benchmark。
- Keyword 命中率与 filters 保留率应来自真实 query distribution;表的总行数本身不能决定是否迁移搜索。
- PostgreSQL indexes 与 Job row 在同一事务维护;独立 Search Service 被建模为约 1 秒 refresh,再叠加 indexing backlog。
- 生产路径使用 Outbox / CDC -> durable Queue -> Indexer;小规模版本可以省略 Queue,但不能同步双写 PostgreSQL 与 Search Service。
- Result cache 默认关闭;只有 normalized popular-query / first-page 的实测 hit rate 足够高时,才使用 30 秒 TTL。Search session 则保存 bounded Top 1,000 job IDs 几分钟,换取稳定分页而非第一次查询加速。
- 无论搜索读哪套 index,Application API 都以 PostgreSQL 当前 Job.status 作为最终正确性判断。