在访问document时,会返回一个version
字段:
如果后续对该document不断进行更新操作,version会递增,但Elasticsearch并不会存储历史的版本数据。当删除该文档时,会默认保留60s该版本号
以前Elasticsearch通过该version id实现乐观并发控制(optimistic concurrency control)
,但现在弃用了
另外,通过version的值,我们可以看出来该文档被修改过几次,但version的功能仅限于此了。
假设有这么一个场景,A和B同时拿到了商品的库存(in_stock
= 6), A产生了购买操作,将in_stock
更新为5
此时B也产生了购买操作,也将in_stock
更新为5。这样计算肯定是有问题的
所以要对数据操作实现并发控制,常见的方式有以下两种:
以前ES使用version id来实现optimictic concurrency control
,在更新数据时携带version id,例如针对上面的场景,A更新数据时携带version=1
, 此时Elasticsearch验证没问题,更新成功后,version id变为2
B下次更新时,也携带了原来的version id=1
,但此时数据版本为2,所以会更新失败:
现在ES使用 _seq_no
(sequence number) 和 _primary_term
(primary term) 来确保文档的旧版本不会覆盖新的版本。sequence number
在每次操作后递增,因此新的操作的_seq_no
一定高于老的操作的_seq_no
。
获取Document的当前_seq_no
:
使用低版本的_seq_no
尝试更新数据,发现会报错 version_conflict:
使用相同的_seq_no
来更新数据,成功更新并返回新的_seq_no
如果数据在我们读取和写入的间隔中发生了变化,更新就会失败。这时候就由程序来决定如何处理这个冲突。例如,它可以重新读取新数据(获取最新的_seq_no
)来进行更新,又或者它可以将这一情况直接反馈给用户。