技术博客 技术博客
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • mysql

    • MySQL 问题汇总
    • MySQL 索引介绍
    • MySQL 锁介绍
    • MySQL 索引优化工具 explain
    • MySQL 主从复制(GTID)
    • MySQL 8安装
    • MySQL 8.x新特性总结
    • MySQL UDF以及新类型JSON
    • MySQL 高可用MGR(一) 理论
    • MySQL 高可用MGR(二) 搭建
    • MySQL 高可用MGR(三) 测试
  • Elasticsearch

    • ES 7.8.0(一) 入门介绍
    • ES 7.8.0(二) 读、写和写索引流程以及文档分析过程
    • ES 7.8.0(三) 文档冲突
  • mongodb

    • mongodb
  • hadoop

    • Hadoop 伪分布式及集群
    • Hadoop 指令
    • Hadoop 读写流程详解
    • Hadoop SpringBoot集成
    • Hadoop MapReduce机制
    • Hadoop YARN
    • Hadoop MapReduce配置和编写job及数据倾斜的解决
    • Hadoop MapReduce自定义格式输入输出
  • clickhouse

    • ClickHouse 介绍及安装
    • ClickHouse 数据类型
    • ClickHouse 表引擎
    • ClickHouse SQL操作
    • ClickHouse 副本配置
    • ClickHouse 分片与集群部署
    • ClickHouse Explain及建表优化
    • ClickHouse 语法优化规则
    • ClickHouse 查询优化
    • ClickHouse 数据一致性
    • ClickHouse 物化视图
    • ClickHouse MaterializeMySQL引擎
    • ClickHouse 监控及备份
  • hbase

    • Hbase 介绍及安装
    • Hbase 优化
    • Hbase phoenix安装及使用
    • Hbase LSM-TREE
  • hive

    • Hive 介绍及安装
    • Hive 内外部表、分区表、分桶表概念及hiveSQL命令
    • Hive 数据类型
    • Hive 函数 MySQL联合
    • Hive 数据倾斜和优化
    • Hive Sqoop安装及指令
  • flink

    • Flink 介绍及安装
    • Flink 配置介绍及Demo
    • Flink API讲解
    • Flink 运行架构
    • Flink 时间语义及Watermark
    • Flink 状态管理
    • Flink 容错,检查点,保存点
    • Flink 状态一致性
    • Flink Table API 和 Flink SQL
    • Flink CEP编程
    • Flink Joining编程
    • Flink CDC
  • flume

    • Flume 日志收集系统介绍及安装
    • Flume Source支持的类型
    • Flume Sink支持的类型
    • Flume Channel支持的类型
    • Flume Selector
    • Flume Interceptor拦截器类型
    • Flume Process
  • sqlite

    • SQLite介绍

ES 7.8.0(三) 文档冲突

文档冲突就是你在访问一个文档的时候,别人也在访问这个文档,正常来说文档的最终版本,应该是最后一个修改的人,而且这种方式只适合用于全量修改,但是如果我是局部修改,就会造成把前面修改文档的内容也覆盖掉,这就是文档冲突。

解决这种文档冲突的方式,在数据库领域中有两种方式用来确保并发更新时变更不会丢失:

  • 悲观锁
    这种方式被关系型数据库广泛使用,他假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。一个典型的例子是读取一行数据之前先将其锁住,确保只有方式锁的线程能够对这行数据进行修改。
  • 乐观锁
    ES 中使用的这种方法,假定冲突时不可能发生的,并且不会阻塞正在尝试的操作。然而,如果数据在读写当中被修改,更新将会失败。应用程序接下来决定该如何解决冲突。例如,可以重试更新,使用新的数据,或者将相关情况报告给用户。

ES 是分布式的,当文档创建、更新和删除时,新版本的文档必须复制到集群中的其他节点。ES 也是异步和并发的,这意味着这些复制请求被并行发送,并且达到目的时也许顺序是乱的。ES 需要一种方法确保文档的旧版本不会覆盖新的版本。

每个文档都有一个_version(版本)号,当文档被修改时版本号递增。ES 使用这个 version 号来确保变更以正确顺序得到执行。如果旧版本的文档在新版本之后到达,它可以被简单的忽略。

以下演示 ES 对于版本号的使用

# 查询数据
curl --location --request GET 'http://10.240.30.93:9200/user/_doc/l76GEIEBBfzVdzdvUxQl'

{
    "_index": "user",
    "_type": "_doc",
    "_id": "l76GEIEBBfzVdzdvUxQl",
    "_version": 1, // 默认版本
    "_seq_no": 0, // 序列号
    "_primary_term": 3,
    "found": true,
    "_source": {
        "name": "zhangsan"
    }
}

# 修改数据
curl --location --request POST 'http://10.240.30.93:9200/user/_update/l76GEIEBBfzVdzdvUxQl' \
--header 'Content-Type: application/json' \
--data-raw '{
    "doc":{
        "name": "zhangsan1"
    }
}'

{
    "_index": "user",
    "_type": "_doc",
    "_id": "l76GEIEBBfzVdzdvUxQl",
    "_version": 2, // 版本递增
    "result": "updated",
    "_shards": {
        "total": 3,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1, // 序列号也增加了
    "_primary_term": 3 // 主分片次数
}

# 如果针对以上有并发修改,都修改name字段,我们可以指定 if_seq_no 和 if_primary_term 修改
curl --location --request POST 'http://10.240.30.93:9200/user/_update/l76GEIEBBfzVdzdvUxQl?if_seq_no=1&if_primary_term=3' \
--header 'Content-Type: application/json' \
--data-raw '{
    "doc":{
        "name": "zhangsan2"
    }
}'

# 当然我们也可以指定他的版本,但是version的值一定要比原值高
curl --location --request POST 'http://10.240.30.93:9200/user/_doc/l76GEIEBBfzVdzdvUxQl?version=4&version_type=external' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "zhangsan2"
}'

{
    "_index": "user",
    "_type": "_doc",
    "_id": "l76GEIEBBfzVdzdvUxQl",
    "_version": 4,
    "result": "updated",
    "_shards": {
        "total": 3,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 3,
    "_primary_term": 3
}
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  • _seq_no
     严格递增的顺序号,每个文档一个,Shard 级别严格递增,保证后写入的 Doc 的_seq_no 大于先写入的 Doc 的_seq_no。
     任何类型的写操作,包括 index、create、update 和 Delete,都会生成一个_seq_no。
     每个文档在使用 Lucene 的 document 操作接口之前,会获取到一个_seq_no,这个_seq_no 会以系统保留 Field 的名义存储到 Lucene 中,文档写入 Lucene 成功后,会标记该 seq_no 为完成状态,这时候会使用当前 seq_no 更新 local_checkpoint。

  • _primary_term
      _primary_term 也和_seq_no 一样是一个整数,每当 Primary Shard 发生重新分配时,比如重启,Primary 选举等,_primary_term 会递增 1。
     _primary_term 主要是用来恢复数据时处理当多个文档的_seq_no 一样时的冲突,避免 Primary Shard 上的写入被覆盖。

上次更新: 6/11/2025, 4:10:30 PM
ES 7.8.0(二) 读、写和写索引流程以及文档分析过程
mongodb

← ES 7.8.0(二) 读、写和写索引流程以及文档分析过程 mongodb→

Theme by Vdoing | Copyright © 2023-2025
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式