上机动手实战基于_version进行乐观并发控制


1.先构造一条数据

PUT /test_index/test_type/7
{
"test_field":"test test"
}
2.模拟两个客户端,都获取到了同一条数据

GET /test_index/test_type/7
1
结果:

{
"_index": "test_index",
"_type": "test_type",
"_id": "7",
"_version": 1,
"found": true,
"_source": {
"test_field": "test test"
}
}
3.其中一个客户端,先更新了一下这个数据
同时带上数据的版本号,确保说,es中数据的版本号,跟客户端中的数据的版本号相同才能修改

PUT /test_index/test_type/7?version=1
{
"test_field":"test client1"
}
结果version变为2

PUT /test_index/test_type/7?version=1
{
"test_field":"test client1"
}
4.另外一个客户端尝试基于version=1的数据去进行修改,同样带上version的版本号,进行乐观锁的并发控制

PUT /test_index/test_type/7?version=1
{
"test_field":"test client2"
}
结果:

{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[test_type][7]: version conflict, current version [2] is different than the one provided [1]",
"index_uuid": "Zt6VyFvpQw60VmopRZ56UA",
"shard": "3",
"index": "test_index"
}
],
"type": "version_conflict_engine_exception",
"reason": "[test_type][7]: version conflict, current version [2] is different than the one provided [1]",
"index_uuid": "Zt6VyFvpQw60VmopRZ56UA",
"shard": "3",
"index": "test_index"
},
"status": 409
}

5.在乐观锁成功阻止并发问题之后,尝试正确的完成更新
首先查看当前的版本号

GET /test_index/test_type/7

根据版本号把对应的version去put(可能这个步骤需要反复执行好几次,才能成功,特别是在多线程并发更新同一条数据很频繁的情况下)

PUT /test_index/test_type/7?version=2
{
"test_field":"test client2"
}

结果:

{
"_index": "test_index",
"_type": "test_type",
"_id": "7",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 2
}

基于内部的version

1.先构造一条数据

PUT /test_index/test_type/9
{
"test_field":"test1"
}

2.模拟两个客户端同时查询到这条数据

GET /test_index/test_type/9

结果:

{
"_index": "test_index",
"_type": "test_type",
"_id": "9",
"_version": 1,
"found": true,
"_source": {
"test_field": "test1"
}
}

3.第一个客户端先进行修改,此时客户端程序是在自己的数据库中获取到了这条数据的最新版本号,比如说2

PUT /test_index/test_type/9?version=2&version_type=external
{
"test_field":"test client1"
}

成功:

{
"_index": "test_index",
"_type": "test_type",
"_id": "9",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 2
}

4.模拟第二个客户端,同时拿到了自己数据库中的哪个版本号,也是2,同时基于version=2发起了修改

PUT /test_index/test_type/9?version=2&version_type=external
{
"test_field":"test client2"
}

错误了:

{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[test_type][9]: version conflict, current version [2] is higher or equal to the one provided [2]",
"index_uuid": "Zt6VyFvpQw60VmopRZ56UA",
"shard": "1",
"index": "test_index"
}
],
"type": "version_conflict_engine_exception",
"reason": "[test_type][9]: version conflict, current version [2] is higher or equal to the one provided [2]",
"index_uuid": "Zt6VyFvpQw60VmopRZ56UA",
"shard": "1",
"index": "test_index"
},
"status": 409
}


5.在并发控制成功后,重新基于最新的版本号发起更新
获取最新的数据

GET /test_index/test_type/9?
1
{
"_index": "test_index",
"_type": "test_type",
"_id": "9",
"_version": 2,
"found": true,
"_source": {
"test_field": "test client1"
}
}

指定version为3比原来的大

PUT /test_index/test_type/9?version=3&version_type=external
{
"test_field":"test client2"
}

成功了:

{
"_index": "test_index",
"_type": "test_type",
"_id": "9",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 2
}
————————————————
版权声明:本文为CSDN博主「知道的越多 那么不知道的就越多」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42061487/article/details/102013826

posted @ 2022-02-17 21:15  小猪冒泡  阅读(76)  评论(0编辑  收藏  举报