<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 處理沖突 當使用`index` API更新文檔的時候,我們讀取原始文檔,做修改,然后將**整個文檔(whole document)**一次性重新索引。最近的索引請求會生效——Elasticsearch中只存儲最后被索引的任何文檔。如果其他人同時也修改了這個文檔,他們的修改將會丟失。 很多時候,這并不是一個問題。或許我們主要的數據存儲在關系型數據庫中,然后拷貝數據到Elasticsearch中只是為了可以用于搜索。或許兩個人同時修改文檔的機會很少。亦或者偶爾的修改丟失對于我們的工作來說并無大礙。 但有時丟失修改是一個**很嚴重**的問題。想象一下我們使用Elasticsearch存儲大量在線商店的庫存信息。每當銷售一個商品,Elasticsearch中的庫存就要減一。 一天,老板決定做一個促銷。瞬間,我們每秒就銷售了幾個商品。想象兩個同時運行的web進程,兩者同時處理一件商品的訂單: ![img-data-lww](https://raw.githubusercontent.com/looly/elasticsearch-definitive-guide-cn/master/images/elas_0301.png) `web_1`讓`stock_count`失效是因為`web_2`沒有察覺到`stock_count`的拷貝已經過期(譯者注:`web_1`取數據,減一后更新了`stock_count`。可惜在`web_1`更新`stock_count`前它就拿到了數據,這個數據已經是過期的了,當`web_2`再回來更新`stock_count`時這個數字就是錯的。這樣就會造成看似賣了一件東西,其實是賣了兩件,這個應該屬于幻讀。)。結果是我們認為自己確實還有更多的商品,最終顧客會因為銷售給他們沒有的東西而失望。 變化越是頻繁,或讀取和更新間的時間越長,越容易丟失我們的更改。 在數據庫中,有兩種通用的方法確保在并發更新時修改不丟失: ### 悲觀并發控制(Pessimistic concurrency control) 這在關系型數據庫中被廣泛的使用,假設沖突的更改經常發生,為了解決沖突我們把訪問區塊化。典型的例子是在讀一行數據前鎖定這行,然后確保只有加鎖的那個線程可以修改這行數據。 ### 樂觀并發控制(Optimistic concurrency control): 被Elasticsearch使用,假設沖突不經常發生,也不區塊化訪問,然而,如果在讀寫過程中數據發生了變化,更新操作將失敗。這時候由程序決定在失敗后如何解決沖突。實際情況中,可以重新嘗試更新,刷新數據(重新讀取)或者直接反饋給用戶。 ## 樂觀并發控制 Elasticsearch是分布式的。當文檔被創建、更新或刪除,文檔的新版本會被復制到集群的其它節點。Elasticsearch即是同步的又是異步的,意思是這些復制請求都是平行發送的,并**無序(out of sequence)**的到達目的地。這就需要一種方法確保老版本的文檔永遠不會覆蓋新的版本。 上文我們提到`index`、`get`、`delete`請求時,我們指出每個文檔都有一個`_version`號碼,這個號碼在文檔被改變時加一。Elasticsearch使用這個`_version`保證所有修改都被正確排序。當一個舊版本出現在新版本之后,它會被簡單的忽略。 我們利用`_version`的這一優點確保數據不會因為修改沖突而丟失。我們可以指定文檔的`version`來做想要的更改。如果那個版本號不是現在的,我們的請求就失敗了。 Let's create a new blog post: 讓我們創建一個新的博文: ```Javascript PUT /website/blog/1/_create { "title": "My first blog entry", "text": "Just trying this out..." } ``` 響應體告訴我們這是一個新建的文檔,它的`_version`是`1`。現在假設我們要編輯這個文檔:把數據加載到web表單中,修改,然后保存成新版本。 首先我們檢索文檔: ```Javascript GET /website/blog/1 ``` 響應體包含相同的`_version`是`1` ```Javascript { "_index" : "website", "_type" : "blog", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "title": "My first blog entry", "text": "Just trying this out..." } } ``` 現在,當我們通過重新索引文檔保存修改時,我們這樣指定了`version`參數: ```Javascript PUT /website/blog/1?version=1 <1> { "title": "My first blog entry", "text": "Starting to get the hang of this..." } ``` - <1> 我們只希望文檔的`_version`是`1`時更新才生效。 This request succeeds, and the response body tells us that the `_version` has been incremented to `2`: 請求成功,響應體告訴我們`_version`已經增加到`2`: ```Javascript { "_index": "website", "_type": "blog", "_id": "1", "_version": 2 "created": false } ``` 然而,如果我們重新運行相同的索引請求,依舊指定`version=1`,Elasticsearch將返回`409 Conflict`狀態的HTTP響應。響應體類似這樣: ```Javascript { "error" : "VersionConflictEngineException[[website][2] [blog][1]: version conflict, current [2], provided [1]]", "status" : 409 } ``` 這告訴我們當前`_version`是`2`,但是我們指定想要更新的版本是`1`。 我們需要做什么取決于程序的需求。我們可以告知用戶其他人修改了文檔,你應該在保存前再看一下。而對于上文提到的商品`stock_count`,我們需要重新檢索最新文檔然后申請新的更改操作。 所有更新和刪除文檔的請求都接受`version`參數,它可以允許在你的代碼中增加樂觀鎖控制。 ## 使用外部版本控制系統 一種常見的結構是使用一些其他的數據庫做為主數據庫,然后使用Elasticsearch搜索數據,這意味著所有主數據庫發生變化,就要將其拷貝到Elasticsearch中。如果有多個進程負責這些數據的同步,就會遇到上面提到的并發問題。 如果主數據庫有版本字段——或一些類似于`timestamp`等可以用于版本控制的字段——是你就可以在Elasticsearch的查詢字符串后面添加`version_type=external`來使用這些版本號。版本號必須是整數,大于零小于`9.2e+18`——Java中的正的`long`。 外部版本號與之前說的內部版本號在處理的時候有些不同。它不再檢查`_version`是否與請求中指定的**一致**,而是檢查是否**小于**指定的版本。如果請求成功,外部版本號就會被存儲到`_version`中。 外部版本號不僅在索引和刪除請求中指定,也可以在**創建(create)**新文檔中指定。 例如,創建一個包含外部版本號`5`的新博客,我們可以這樣做: ```Javascript PUT /website/blog/2?version=5&version_type=external { "title": "My first external blog entry", "text": "Starting to get the hang of this..." } ``` 在響應中,我們能看到當前的`_version`號碼是`5`: ```Javascript { "_index": "website", "_type": "blog", "_id": "2", "_version": 5, "created": true } ``` 現在我們更新這個文檔,指定一個新`version`號碼為`10`: ```Javascript PUT /website/blog/2?version=10&version_type=external { "title": "My first external blog entry", "text": "This is a piece of cake..." } ``` 請求成功的設置了當前`_version`為`10`: ```Javascript { "_index": "website", "_type": "blog", "_id": "2", "_version": 10, "created": false } ``` 如果你重新運行這個請求,就會返回一個像之前一樣的沖突錯誤,因為指定的外部版本號不大于當前在Elasticsearch中的版本。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看