ES权威指南[官方文档学习笔记]-37optimisticconcurrencycontrol

作者:袖梨 2026-08-20

es:http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html

ES权威指南[官方文档学习笔记]-37optimisticconcurrencycontrol

下一篇:http://my.oschina.net/qiangzigege/blog/264361

内容:

es是一个分布式的系统,当文档创建,更新或者删除,新版本的文档必须复制到其它节点,

es同时也是异步和并发的,这意味着这些备份请求同时发送,并且可能乱序到达目的地,

这就需要一种策略来保证旧版本的文档不会覆盖新版本的文档。

当我们讨论索引,get/delete请求,我们指出:每个文档有一个_version字段,当文档改变时

这个字段自增,es使用这个数字来保证改变的应用按照正确的顺序来做,

如果一个旧的文档在新文档之后来到,简单的被丢弃。

我们可以通过_version字段来受益,保证冲突不会导致数据丢失。

我们通过指定文档的版本号。如果版本号不是最新的,请求将会失败。

先创建一个文档。

PUT /website/blog/1/_create

{

"title": "My first blog entry",

"text": "Just trying this out..."

}

响应体告诉我们这是一个新创建的文档,版本号为1

现在想象一下,我们需要编辑这个文档,我们下载这个文档,改变,保存。

先检索这个文档。

GET /website/blog/1

响应体如下:

{

"_index" : "website",

"_type" : "blog",

"_id" : "1",

"_version" : 1,

"found" : true,

"_source" : {

"title": "My first blog entry",

"text": "Just trying this out..."

}

}

当我们尝试修改保存改变,我们指定了版本号。

PUT /website/blog/1?version=1

{

"title": "My first blog entry",

"text": "Starting to get the hang of this..."

}

请求成功,响应体告诉我们版本号变为2.

{

"_index": "website",

"_type": "blog",

"_id": "1",

"_version": 2

"created": false

}

尽管如此,如果我们再去发同样的请求,也就是version=1,

es将返回一个409冲突。

响应体如下:

{

"error" : "VersionConflictEngineException[[website][2] [blog][1]:

version conflict, current [2], provided [1]]",

"status" : 409

}

告诉我们,目前的版本号是2,但是我们想要更新版本号1的文档。

我们可以告诉用户某人已经改变了文档,然后应该在重新尝试前看一下改变。

我们也可以重新检索最新文档再改变。

所有的API(update/delete)接收一个版本号参数,容许我们应用乐观并发控制。

使用外部系统的版本号

一个常用的设置是:使用其它数据库作为主数据存储,es让数据可搜索,

也就是说,所有对主数据库的改变需要复制到es.如果有多个进程涉及到数据同步,你将会碰到并发问题。

如果你的主数据库已经有一个版本号,或者时间戳之类,你可以使用这些值,通过添加

version_type=external.

版本号必须是整数,大于0,小于9.2e+18 。

这种方式跟内部的版本号有点区别:

之前是判断es里的版本号和用户提交的参数是否一致,现在是比较目前的版本号是否比参数小,

如果请求成功,外部的版本号就成功存储。

外部的版本号不仅可以在索引和删除一个文档时指定,创建新文档时也可以指定。

比如说,创建一个新的blog文档,带有一个版本号5

PUT /website/blog/2?version=5&version_type=external

{

"title": "My first external blog entry",

"text": "Starting to get the hang of this..."

}

响应体:

{

"_index": "website",

"_type": "blog",

"_id": "2",

"_version": 5,

"created": true

}

更新

PUT /website/blog/2?version=10&version_type=external

{

"title": "My first external blog entry",

"text": "This is a piece of cake..."

}

响应体:

{

"_index": "website",

"_type": "blog",

"_id": "2",

"_version": 10,

"created": false

}

如果你重新执行,会失败,因为版本号不够大。你懂的。

相关文章

精彩推荐