Elasticsearch 并发修改乐观锁

news/2024/7/6 3:04:33

来自: http://blog.csdn.net//jiao_fuyou/article/details/50482117

 

版本控制的一个例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
curl -XPOST http://localhost:9200/test/test/1 -d '{"msg": "test"}'
{
     "_index" : "test" ,
     "_type" : "test" ,
     "_id" : "1" ,
     "_version" : 1,
     "created" : true
}
curl -XPOST http://localhost:9200/test/test/1 -d '{"msg": "test"}'
{
     "_index" : "test" ,
     "_type" : "test" ,
     "_id" : "1" ,
     "_version" : 2,
     "created" : true
}
curl -XPOST http://localhost:9200/test/test/1?version=1 -d '{"msg": "test"}'
{
     "error" : "RemoteTransportException[[elasticsearch_226][inet[/172.16.18.226:9300]][indices:data/write/index]]; nested: VersionConflictEngineException[[test][0] [test][1]: version conflict, current [4], provided [1]]; " ,
     "status" : 409
}

提示:版本冲突

使用外部系统提供的版本号

Elasticsearch 的乐观锁,可以使用外部系统提供的版本号:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -XPOST http://localhost:9200/test/test/1?version=10&version_type=external -d '{"msg": "test"}'
{
     "_index" : "test" ,
     "_type" : "test" ,
     "_id" : "1" ,
     "_version" : 10,
     "created" : true
}
 
curl -XPOST http://localhost:9200/test/test/1?version=9&version_type=external -d '{"msg": "test"}'
{
     "error" : "VersionConflictEngineException[[test][0] [test][1]: version conflict, current [10], provided [9]]" ,
     "status" : 409
}

这时Elasticsearch将只检查提供的版本是否比当前保存在索引中的版本大(大多少不重要),如果是成功,否则失败。

Elasticsearch内部版本号

在Elasticsearch中,更新请求实际上是分为两个阶段,获取文档,修改文档,然后保存文档。
那么当两个更新请求同时要修改文档的时候,系统乐观的认为不会有两个并发请求对一个系统操作。
文档原本的版本为1,请求A获取了version为1的文档,请求B也获取了version为1的文档,然后请求A修改完文档后,并且先执行了保存操作,这个时候,系统中的文档version变为了2。
这个时候,B再执行保存操作的时候,告诉系统我要修改version为1的文档。系统就会抛出一个错误,说文档版本不匹配。然后这个错误由应用程序自己来进行控制。
这种机制在请求量大的时候会比悲观锁机制好。但是缺点是需要程序处理版本冲突错误,可能一般的方法是封装更新操作,并且设置重复重试次数。

注意这里的更新指的是:

?
1
curl -XPOST http://localhost:9200/test/test/1/_update -d '{"msg": "test"}'

而不是:

?
1
curl -XPOST http://localhost:9200/test/test/1 -d '{"msg": "test"}'

这个是create,这种在ES内部没有乐观锁的概念,是直接覆盖,这种想解决数据被覆盖,就要显示的带着version

下面的程序,并发6个进程同时批量更新一个文档,在结果能看到有的请求出错了,返回版本冲突。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
 
require_once dirname(__FILE__). '/../shjf/vendor/autoload.php' ;
 
$client = new Elasticsearch\Client([ 'hosts' => [ '172.16.18.226:9200' ]]);
 
for ($i=0;$i<5;$i++){   
     if (pcntl_fork() == 0) break;
}
 
$params=[
     'index' => 'test' ,
     'type'  => 'test' ,
     'body' => [],
]; 
 
for ($i=0;$i<1;$i++){
     $params[ 'body' ][] = [ 'update' => [ '_id' => 111]];
     $params[ 'body' ][] = [ "doc" => [ "id" => $i]];
}
try
{
     $result = $client->bulk($params);
     var_dump($result) . "\n" ;
}
catch(Exception $e)
{
     echo $e->getMessage() . "\n" ;
     $info = $client->transport->getLastConnection()->getLastRequestInfo();
     print_r($info);
     exit;
}
 
echo "end\n" ;
 
?>
 
{
   "took" :1,
   "errors" : true ,
   "items" :[
     { "update" : {
         "_index" : "test" ,
         "_type" : "test" ,
         "_id" : "111" ,
         "status" :409,
         "error" : "VersionConflictEngineException[[test][0] [test][111]: version conflict, current [3], provided [2]]" }
     }
   ]
}

参考资料:

  • Elasticsearch官网:
    • https://www.elastic.co/guide/en/elasticsearch/reference/2.1/docs-update.html
    • https://www.elastic.co/guide/en/elasticsearch/guide/master/partial-updates.html
    • https://www.elastic.co/guide/en/elasticsearch/guide/master/optimistic-concurrency-control.html
  • 《Elasticsearch权威指南》处理冲突
    • http://download.csdn.net/detail/xtjsxtj/9398862

http://www.niftyadmin.cn/n/3297890.html

相关文章

题解 P1886 【滑动窗口】

我用的双端队列来做的 题意就不讲了吧。可以看出来最大值和最小值是同一个问题&#xff0c;改一下大于号和小于号就行了。所以我只讲怎么求最大值吧。 定义一个双端队列&#xff08;相当于queue两端都可以插入或弹出&#xff0c;可以自行百度&#xff09; deque<pair> a,…

题解 CF1060B 【Maximum Sum of Digits】

先讲一下思路 首先输入一个数s; 然后要把S拆为AB&#xff1b; 那么&#xff0c;A的各个数位要尽可能大&#xff1b; 一&#xff1a;找出S的位数CNT,A加上CNT-1位9&#xff1b; 比如S2233213123的话&#xff0c;A一开始就等于 999999999 二&#xff1a;A的第一位为S第一位数字-1…

Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】 ...

http://www.blogjava.net/masfay/archive/2012/07/03/382080.html 前段时间细节的了解了Jedis的使用&#xff0c;Jedis是redis的java版本的客户端实现。本文做个总结&#xff0c;主要分享如下内容&#xff1a;【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【…

使用C++随机生成数据实战

题目地址 今天尝试了一下用C生成数据&#xff0c;参考了这篇文章。 主要过程是你需要先写一个标算 #include<bits/stdc.h> using namespace std; int ans; int main() {cout<<ans<<endl&#xff1b;return 0; } 接着使用这个程序 #include<iostream> #…

【缅怀妈妈系列诗歌】之十五:妈妈,请恕孩儿不孝

【缅怀妈妈系列诗歌】之十五&#xff1a;妈妈&#xff0c;请恕孩儿不孝题记&#xff1a;由于本想给妈妈的坟墓堆砌高一点、大一点、雄伟一点&#xff0c;因封建礼仪约束未能实现而感怀。谨以这一系列文章和诗歌缅怀我病逝的妈妈&#xff0c;祈祷她老人家在天能得以安息&#xf…

[Elasticsearch] 锁

字段折叠(Field Collapsing) 一个常见的需求是通过对某个特定的字段分组来展现搜索结果。我们或许希望通过对用户名分组来返回最相关的博文。对用户名分组意味着我们需要使用到terms聚合。为了对用户的全名进行分组&#xff0c;name字段需要有not_analyzed的原始值&#xff0c;…

面试题目--SQL 查100条数据中的30-40条

面试题目--SQL 查100条数据中的30-40条 分页sql查询在编程的应用很多&#xff0c;主要有存储过程分页和sql分页两种&#xff0c;我比较喜欢用sql分页&#xff0c;主要是很方便。为了提高查询效率&#xff0c;应在排序字段上加索引。 sql分页查询的原理很简单&#xff0c;比如你…

Redis集群技术分类

前言 诚如开篇文章所言&#xff0c;高效运维包括管理的专业化和技术的专业化。前两篇我们主要在说些管理相关的内容&#xff0c;本篇说一下技术专业化。希望读者朋友们能适应这个转换&#xff0c;谢谢。 互联网早在几年前就已进入Web 2.0时代&#xff0c;对后台支撑能力的要求&…