bigywater.tech
Elasticsearch · 105

if_seq_no 与 if_primary_term

真实验证if_seq_no与if_primary_term必须成对传入、缺一不可的参数校验规则,并用正确seq_no配上瞎编primary_term依然被拒绝的真实案例,证明两者是各自独立被精确检查的复合条件而非宽松的任一匹配。

只传其中一个参数
真实都被400拒绝,两者必须成对出现
正确seq_no配错误primary_term
真实依然409失败
两者关系
真实是各自独立被精确检查的复合条件

做的事:真实分别只传if_seq_no、只传if_primary_term这两种"只给一半"的写法,看ES会不会接受

代码真实索引文档拿到_seq_no=0, _primary_term=1 PUT /sp_test/_doc/1?if_seq_no=0 {"n":2} # 真实只传if_seq_no PUT /sp_test/_doc/1?if_primary_term=1 {"n":2} # 真实只传if_primary_term

验证:两种"只给一半"的写法真实都被直接拒绝了,报错精确指出这两个参数必须成对出现

实测 · 本机 Elasticsearch 8.15.0 执行输出
只传if_seq_no=0:
→ 400 "ifSeqNo is set, but primary term is [0]"

只传if_primary_term=1:
→ 400 "ifSeqNo is unassigned, but primary term is [1]"

这组真实报错在请求校验阶段就把规则说清楚了:if_seq_no和if_primary_term真实被设计成必须成对出现,缺一个都真实过不了参数校验这一关。这背后的真实逻辑是:单独一个seq_no真实不足以唯一确定"这是哪一次写入"——本系列上一篇提到过,primary_term真实是主分片故障转移时才会递增的更粗粒度标识,如果只检查seq_no而不检查primary_term,真实有可能在主分片切换的边界场景下,把两个不同"任期"里恰好序号相同的写入操作搞混。

真实验证更关键的一点:故意传正确的seq_no,但配上一个瞎编的primary_term,写入会不会被放行

代码PUT /sp_test/_doc/1?if_seq_no=0&if_primary_term=99 {"n":2} (真实seq_no=0是对的,primary_term=99是真实瞎编的错误值)

验证:哪怕seq_no完全正确,primary_term真实只要对不上,写入依然直接409失败

实测 · 本机执行输出
→ 409 version_conflict_engine_exception:
  "required seqNo [0], primary term [99]. current document has seqNo [0] and primary term [1]"

真实再查文档,确认完全没被改动:
→ {"n": 1}, _seq_no=0, _primary_term=1   ← 真实写入被完整拒绝,文档一个字段都没变
这组真实结果精确证明了if_seq_no和if_primary_term真实是两个独立被检查的复合条件,不存在"seq_no对了就能通过"这种宽松逻辑——本次实测seq_no=0真实跟服务端完全一致,但primary_term=99真实是瞎编的错误值,整条写入依然被真实拒绝,报错信息里真实把"你传的primary_term[99]"和"服务端真实的primary_term[1]"都摊开展示了出来。这组真实验证完整了对乐观并发控制机制的理解:客户端做"比较并交换"判断时,真实必须同时精确提供这两个标识,服务端真实会把它们当成一个不可分割的整体去跟当前文档状态比对,任何一个对不上都会让整次写入真实失败,文档状态真实保持完全不变。

分步演示:if_seq_no与if_primary_term从必须成对出现到各自独立精确校验的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

if_seq_no与if_primary_term必须成对出现且各自独立被精确检查
这一步新验证的参数组合

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 if_seq_no 与 if_primary_term 参数校验
    京ICP备2026067502号-1京公网安备11010502063487号