第八节 处理并发读写操作
1、并发控制的必要性
- 两个 Web 程序同时更新某个⽂档,如果缺乏有效的并发,会导致更改的数据丢失
- 悲观并发控制
- 假定有变更冲突的可能。会对资源加锁,防止冲突。例如数据库⾏锁
- 乐观并发控制
- 假定冲突是不会发⽣的,不会阻塞正在尝试的操作。如果数据在读写中被修改,更新将会失败。 应⽤程序决定如何解决冲突,例如重试更新,使⽤新的数据,或者将错误报告给⽤户
- ES 采⽤的是乐观并发控制
2、ES 的乐观并发控制
- ES 中的⽂档是不可变更的。如果你更新⼀个⽂档,会将就文档标记为删除,同时增加一个全新的⽂档。同时⽂档 的 version 字段加 1
- 内部版本控制
If_seq_no + If_primary_term
- 使⽤外部版本(使⽤其他数据库作为主要数据存储)
version + version_type=external
DELETE products
PUT products
Output
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "products"
}
GET products/_doc/1
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "iphone",
"count" : 100
}
}
2-1 内部版本控制: If_seq_no + If_primary_term
PUT products/_doc/1?if_seq_no=0&if_primary_term=1
{
"title":"iphone",
"count":100
}
Output:
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
if_seq_no=0&if_primary_term=1
- 改变 count 到 99
PUT products/_doc/1?if_seq_no=0&if_primary_term=1
{
"title":"iphone",
"count":99
}
Output: 409 - Conflict
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, required seqNo [0], primary term [1]. current document has seqNo [1] and primary term [1]",
"index_uuid" : "YrNla_cjTweku9BxzjH2Ig",
"shard" : "0",
"index" : "products"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, required seqNo [0], primary term [1]. current document has seqNo [1] and primary term [1]",
"index_uuid" : "YrNla_cjTweku9BxzjH2Ig",
"shard" : "0",
"index" : "products"
},
"status" : 409
}
2-2 使⽤外部版本: version + version_type=external
PUT products/_doc/1?version=30000&version_type=external
{
"title":"iphone",
"count":100
}
Output
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_version" : 30000,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
"_version" : 30000
- 改变 count 到 99
PUT products/_doc/1?version=30000&version_type=external
{
"title":"iphone",
"count":99
}
Output: 409 - Conflict
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, current version [30000] is higher or equal to the one provided [30000]",
"index_uuid" : "YrNla_cjTweku9BxzjH2Ig",
"shard" : "0",
"index" : "products"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, current version [30000] is higher or equal to the one provided [30000]",
"index_uuid" : "YrNla_cjTweku9BxzjH2Ig",
"shard" : "0",
"index" : "products"
},
"status" : 409
}