4.1 写入:Index API 与分片路由


文档摘要

4.1 写入:Index API 与分片路由 本节摘要:写入请求(Index API)发出后,协调节点按"哈希取余"把文档派给某个主分片,校验映射、写内存缓冲与事务日志,等待刷新成段。本节推导路由公式、对比指定 id 与自动生成 id 的语义差别、拆解写路径六步。读懂这一节,doc-1001 在集群里的住址不再神秘,第 8 章的分片搬迁也有了参照物。 写入请求发出之后 一、路由:文档的住址是怎么定的 第 1 章埋的公式现在正式登场。目标分片由三样东西决定:文档 id、索引名(参与哈希种子)、主分片数: 公式虽简单,三个推论值得刻在脑子里。推论一:同 id 重写必然落进同一分片——覆盖语义靠路由稳定性保证。

4.1 写入:Index API 与分片路由

本节摘要:写入请求(Index API)发出后,协调节点按"哈希取余"把文档派给某个主分片,校验映射、写内存缓冲与事务日志,等待刷新成段。本节推导路由公式、对比指定 id 与自动生成 id 的语义差别、拆解写路径六步。读懂这一节,doc-1001 在集群里的住址不再神秘,第 8 章的分片搬迁也有了参照物。

写入请求发出之后

一、路由:文档的住址是怎么定的

第 1 章埋的公式现在正式登场。目标分片由三样东西决定:文档 id、索引名(参与哈希种子)、主分片数:

{ "路由公式的工程形态": { "shard": "hash( routing值 ) mod number_of_primary_shards", "routing默认值": "文档id 自动生成时是随机串 指定时是调用方给的id", "doc-1001示例": "hash(doc-1001)结果为正整数 对3取余得1 落在1号主分片" } }

公式虽简单,三个推论值得刻在脑子里。推论一:同 id 重写必然落进同一分片——覆盖语义靠路由稳定性保证。推论二:主分片数一旦改变,老文档按旧数算出的住址与查询按新数去找的住址对不上,数据"失踪"——这就是分片数不可改的数学根。推论三:routing 参数可以人为指定,把"同一用户的工单"强制塞进同一分片,检索时带上同样的 routing 就只搜一个分片——大客户场景的提速手段,代价是数据分布可能倾斜。

路由与写路径全景

路由与写路径全景

图里最容易被忽视的是 5b:应答客户端成功之前,事务日志必须先落盘。掉电重启后,引擎重放事务日志,把没来得及刷成段的文档补回来——不丢数据立刻可搜是两个不同的承诺,中间隔着 refresh 间隔。

二、指定 id 与自动 id

两种写法对应两种业务形态:

PUT tickets/_doc/doc-1001 { "title": "用户申请退款,处理速度太慢" }
POST tickets/_doc { "title": "从上游队列来的日志型数据 不给id" } # 返回 _id: "xKc_ooB-mVvS7QAa2fF" result: created

指定 id 是幂等的:同 id 再写即覆盖,数据库同步、工单同步这类"上游有主键"的场景必选。自动生成 id 是追加式的:引擎造一个全局概率不重复的串,路由按这个新串计算,写入路径略过"查旧版本"一步,吞吐更高——日志、指标这类天然无主键的数据首选。经验法则:数据有天然主键就指定,没有就用自动 id,别拿时间戳硬造 id(同毫秒碰撞与路由热点双输)。

三、看懂写入响应里的四个字段

{ "_index": "tickets", "_id": "doc-1001", "result": "created", "_seq_no": 12, "_primary_term": 3 }

result 区分 created 与 updated,覆盖与新建一目了然。_seq_no 是分片内单调递增的序号,_primary_term 记录主分片易主次数——这对组合是文档的"版本指纹",4.3 的乐观并发控制全靠它们。同分片内每条变更各领一个更大的序号,谁新谁旧不再靠猜。

常见坑:拿写入成功的应答去立刻搜索,却扑了个空。应答只承诺"不丢",可搜索要等 refresh(默认一秒)。写入后需要立即可见的场景(写完立刻读的交互流),改用索引、更新、批量接口的立即刷新参数(refresh 设为 wait_for 更佳),或干脆按 id 点查——点查不依赖 refresh。

关键直觉:把协调节点想成铁路编组站——车厢(文档)挂上哪趟车(分片)由哈希决定,编组员不关心车厢里装了什么,只按编号扳道岔。想固定车厢与车次的绑定,就给 routing。

考核与自测

考核知识点清单

考核点 达标标准
路由计算 给定文档 id 与主分片数算出落点,说出公式的三个输入
三个推论 解释覆盖语义、分片数不可改、自定义 routing 各自的根据
两种 id 按数据形态选 id 策略,并说明自动 id 吞吐更高的原因
响应四字段 说出 result 与版本指纹组合的含义及后续用途
持久化边界 区分"应答成功""可搜索""真正落盘"三个时刻各由谁保证

动手验证:查一条文档的住址

分片搜索接口能直接回答"这次请求会扇出到哪些分片":

GET tickets/_search_shards?routing=doc-1001 # 返回的分片数组里只有一个对象 路由把请求钉死在单分片 GET tickets/_search_shards # 不带路由 返回全部主分片 普通搜索的扇出面

对比两次返回,推论三的提速机理有了实测注脚:带 routing 的查询少扇出两个分片,网络往返与归并开销同步减少。大客户场景把同一客户的工单写入与查询都钉在同一路由值上,就是这张实验的生产放大版——写入侧与查询侧必须成对出现,单边带上等于没带。

易错点补充

  • 应答成功就以为能搜到:不丢与可见是两个承诺,中间隔着一次刷新,交互流用等待刷新参数或按 id 点查。
  • 自定义 routing 造成倾斜:个别超大租户会把一个分片撑成热点,监控各分片文档数,倾斜时改用复合路由值打散。
  • 拿自增序号当文档 id:全局递增看似无害,但与业务主键并存时容易两套 id 打架,选一种贯穿到底。
  • 写入端从不看分片计数字段:副本失败被应答里的成功标志掩盖,等到节点故障才暴露副本缺口,同步面要日常盯。
  • 混淆"覆盖"与"部分更新":同 id 整条重写会抹掉未携带字段,想保留旧值要用更新接口的合并语义。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U