2021-11-11

Elasticsearch (id、_source、乐观锁 )

一、_document

1、document id生成方式

1.1手动指定

判断是否适合使用手动指定id方式:
当数据来源中存在唯一的标识,这种情况用来指定的id(例如:数据库中的主键)。
当数据是直接存在es中时,这种情况不适合用指定id。
命令: PUT /test/test_index/1

1.2自动生成

命令:POST /test/test_index
特点:自动生成id,长度为20个字符,URL安全,base64编码,GUID生成id的算法,分布式系统并行生成时,不可能会发生重复。

2、 _source 元数据以及定制返回解析

2.1、插入数据

PUT /test1/test_type/1
{
  "name":"张三",
  "性别":"男",
  "年龄":"20"
}

2.2、获取数据

{
  "_index" : "test1",
  "_type" : "test_type",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "张三",
    "性别" : "男",
    "年龄" : "20"
  }
}

_source元数据就是创建一个document的时候,使用body中的json传,get请求会原封不动的返给我们。

2.3、查询指定的字段

GET /test1/test_type/1?_source=name

3、全量替换

3.1、当 document id中存在时,会进行替换;不存在时,则会新增。

注:替换时,原来数据只是物理删除了,数据只是标记为deleted;
当document创建的越来越多的时候,es会在适当的时候,后台会自动删除标记为deleted的document。
delete 也是同样的原理。
3.2、 document强制创建语法:

PUT /test1/test_type/3/_create
{
  "name":"张三",
  "性别":"男",
  "年龄":"23"
}

二、乐观锁

通过版本号控制数据的修改

1、新增一条数据

PUT /test_index/test_index/1
{
   "name" : "张三"  
}

返回数据:

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

2、同时打开两个客户端

同时输入一下命令
es旧版的命令:

PUT /test_index/test_index/1?version=1
{
   "name" : "历史"  
}

更新时带上数据的版本号,只有版本号一致的情况下才可以修改,如果出现版本号不一致的情况或者丢弃该数据或者获取最新的版本号然后在进行更新
_version和external version的区别
ersion_type=external与_version的区别在于,
_version,只有当你提供的version与es中的_version一模一样的时候,才可以进行修改,只要不一样,就报错;
version_type=external的时候,只有当你提供的version比es中的_version大的时候,才能完成修改。

es新版的命令:

客户端A修改

PUT /test_index/test_index/1?if_seq_no=0&if_primary_term=1
{
   "name" : "历史"  
}

返回:

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

另一台客户端B命令:

PUT /test_index/test_index/1?if_seq_no=0&if_primary_term=1
{
   "name" : "历史2"  
}

返回:

{
  "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" : "Tq0aE0OoQ_e9YszH_AU86g",
        "shard" : "0",
        "index" : "test_index"
      }
    ],
    "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" : "Tq0aE0OoQ_e9YszH_AU86g",
    "shard" : "0",
    "index" : "test_index"
  },
  "status" : 409
}

客户端B修改时报错:seqNo 出现冲突。
说明seqNo 已经被修改,需要重新查询后再修改。

重新查询后返回:

{
  "_index" : "test_index",
  "_type" : "test_index",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "历史2"
  }
}

发现seq_no已经变化了,所以修改时需要修改seq_no的值。

上一篇:优秀的开发者每天都在做什么?


下一篇:raft(转)