Elasticsearch使用_version
来确保所有的改变操作都被正确排序。如果一个旧的版本出现在新版本之后,它就会被忽略掉。
我们可以利用_version
的优点来确保我们程序修改的数据冲突不会造成数据丢失。我们可以按照我们的想法来指定_version
的数字。如果数字错误,请求就是失败。
GET 到当前待修改文档的_version数字
GET /website/blog/1
将_version值带入到下一次更新的连接中
PUT /website/blog/1?version=1
修改成功之后_version变成 2
然而,当我们再执行同样的索引请求,并依旧指定version=1
时,Elasticsearch就会返回一个409 Conflict
的响应码,返回内容如下:
{
"error" : "VersionConflictEngineException[[website][2] [blog][1]:
version conflict, current [2], provided [1]]",
"status" : 409
}
所有的有关于更新或者删除文档的API都支持version
这个参数,有了它你就通过修改你的程序来使用乐观并发控制
使用外部系统的版本
还有一种常见的情况就是我们还是使用其他的数据库来存储数据,而Elasticsearch只是帮我们检索数据。这也就意味着主数据库只要发生的变更,就需要将其拷贝到Elasticsearch中。如果多个进程同时发生,就会产生上文提到的那些并发问题。
如果你的数据库已经存在了版本号码,或者也可以代表版本的时间戳
。这是你就可以在Elasticsearch的查询字符串后面添加version_type=external
来使用这些号码。版本号码必须要是大于零小于9.2e+18
(Java中long的最大正值)的整数。
Elasticsearch在处理外部版本号时会与对内部版本号的处理有些不同。它不再是检查_version
是否与请求中指定的数值相同,而是检查当前的_version
是否比指定的数值小。如果请求成功,那么外部的版本号就会被存储到文档中的_version
中。
外部版本号不仅可以在索引和删除请求时使用,还可以在创建时使用。
例如,创建一篇使用外部版本号为5
的博文,我们可以这样操作:
PUT /website/blog/2?version=5&version_type=external
在返回结果中,我们可以发现_version
是5
现在我们更新这个文档,并指定version
为10
PUT /website/blog/2?version=10&version_type=external
请求被成功执行并且version
也变成了10
如果你再次执行这个命令,你会得到之前的错误提示信息,因为你所指定的版本号并没有大于当前Elasticsearch中的版本号。