2023-08-08  阅读(1)
原文作者:Ressmix 原文地址:https://www.tpvlog.com/article/146

我们知道,在数据库中,如果多个客户端线程同时对一条记录进行增删改查,数据库会有锁机制保证并发访问的数据一致性。在Elasticsearch中,document就表示一条数据记录,那么Elasticsearch是如何对document的并发访问进行控制的呢?

本章,我们就以一个电商下单的案例为背景,介绍document的并发控制机制。

一、案例背景

我们现在有一个商品管理系统,底层采用Elasticsearch存储商品信息(包括商品ID、商品库存等)。现在,用户需要进行下单操作,流程如下:

  1. 用户浏览商品,此时发送请求到商品管理系统,查询商品信息;
  2. 用户下单购买;
  3. 支付成功后,发送请求到商品管理系统,扣减商品库存(库存-1)。

二、version版本号

Elasticsearch内部采用了版本号机制对document的并发修改进行控制 。所谓版本号,本质是一种乐观锁。

3.1 _version

我们往Elasticsearch写入document数据时,ES会自动为document生成一个版本号_version,比如我们插入一条id为6的数据,返回结果里的_version就表示这条数据的版本号:

    PUT /test_index/test_type/6
    {
      "test_field": "test test"
    }
    
    返回:
    {
      "_index": "test_index",
      "_type": "test_type",
      "_id": "6",
      "_version": 1,
      "result": "created",
      "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
      },
      "created": true
    }

第一次创建document时,它的_version版本号是1;以后,每次对这个document修改或删除时,_version版本号会自动加1(哪怕是删除,也会对这条数据的版本号加1)。

3.2 版本控制

我们来看下ES的数据版本控制流程,整个业务执行流程如下:

  1. 假设我们现在有两个线程A和B,同时读取到了商品信息,此时获取到的document的_version版本号是相同的,假设都是1;
  2. A线程在本地将库存减1后,发送PUT更新请求,请求里带上了版本号PUT /product/storage/1?version=1
  3. ES收到请求后,对数据进行更新,然后将版本号+1;
  4. B线程在本地将库存减1后,发送PUT更新请求,请求里也带上了版本号1,PUT /product/storage/1?version=1
  5. ES收到请求后,发现id为1的document的版本号已经是2了,而B线程的更新请求里带的版本号还是1,两者不一样,于是拒绝更新,返回报错。

3.3 external version

Elasticsearch还提供了一个外部版本号的功能,就是说可以不用它提供的内部_version版本号来进行并发控制,可以基于你自己维护的一个版本号来进行并发控制。

内部版本语法:

    ?version=1

自定义版本号语法:

    ?version=1&version_type=external

注意,当version_type=external的时,只有当提供的version比Elasticsearch中的_version大的时候,才能完成修改。

我们来看个例子,比如现在写入了这样一条记录,,可以看到_version版本号是1:

    PUT /test_index/test_type/8
    {
      "test_field": "test"
    }
    
    {
      "_index": "test_index",
      "_type": "test_type",
      "_id": "8",
      "_version": 1,
      "result": "created",
      "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
      },
      "created": true
    }

然后,A线程先进行修改,带上了外部版本号2:

    PUT /test_index/test_type/8?version=2&version_type=external
    {
      "test_field": "test client 1"
    }
    
    {
      "_index": "test_index",
      "_type": "test_type",
      "_id": "8",
      "_version": 2,
      "result": "updated",
      "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
      },
      "created": false
    }

接着,B线程也进行修改,带上了外部版本号2,可以看到报错了,因为当version_type=external的时,只有当提供的version比Elasticsearch中的_version大的时候,才能完成修改:

    PUT /test_index/test_type/8?version=2&version_type=external
    {
      "test_field": "test client 2"
    }
    
    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[test_type][8]: version conflict, current version [2] is higher or equal to the one provided [2]",
            "index_uuid": "6m0G7yx7R1KECWWGnfH1sw",
            "shard": "1",
            "index": "test_index"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[test_type][8]: version conflict, current version [2] is higher or equal to the one provided [2]",
        "index_uuid": "6m0G7yx7R1KECWWGnfH1sw",
        "shard": "1",
        "index": "test_index"
      },
      "status": 409
    }

三、总结

本章,我们讲解了document的并发控制原理,其核心就是基于内部的版本号机制,下一章,我们来看下document数据的路由原理。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文