楽観的同時実行制御

Elasticsearchは分散型です。ドキュメントが作成、更新、または削除されると、新しいバージョンのドキュメントはクラスター内の他のノードに複製される必要があります。Elasticsearchは非同期かつ同時実行であり、これらの複製リクエストは並行して送信され、宛先に到着する順序が異なる場合があります。Elasticsearchは、古いバージョンのドキュメントが新しいバージョンを上書きしないようにする方法が必要です。

古いバージョンのドキュメントが新しいバージョンを上書きしないようにするために、ドキュメントに対して実行されるすべての操作には、その変更を調整するプライマリシャードによってシーケンス番号が割り当てられます。シーケンス番号は各操作ごとに増加し、そのため新しい操作は古い操作よりも高いシーケンス番号を持つことが保証されます。Elasticsearchは、操作のシーケンス番号を使用して、新しいドキュメントバージョンが小さいシーケンス番号が割り当てられた変更によって上書きされないようにします。

たとえば、次のインデックス作成コマンドはドキュメントを作成し、初期シーケンス番号とプライマリタームを割り当てます:

Python

  1. resp = client.index(
  2. index="products",
  3. id="1567",
  4. document={
  5. "product": "r2d2",
  6. "details": "A resourceful astromech droid"
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.index(
  2. index: 'products',
  3. id: 1567,
  4. body: {
  5. product: 'r2d2',
  6. details: 'A resourceful astromech droid'
  7. }
  8. )
  9. puts response

Js

  1. const response = await client.index({
  2. index: "products",
  3. id: 1567,
  4. document: {
  5. product: "r2d2",
  6. details: "A resourceful astromech droid",
  7. },
  8. });
  9. console.log(response);

コンソール

  1. PUT products/_doc/1567
  2. {
  3. "product" : "r2d2",
  4. "details" : "A resourceful astromech droid"
  5. }

割り当てられたシーケンス番号とプライマリタームは、応答の_seq_noおよび_primary_termフィールドに表示されます:

コンソール-結果

  1. {
  2. "_shards": {
  3. "total": 2,
  4. "failed": 0,
  5. "successful": 1
  6. },
  7. "_index": "products",
  8. "_id": "1567",
  9. "_version": 1,
  10. "_seq_no": 362,
  11. "_primary_term": 2,
  12. "result": "created"
  13. }

Elasticsearchは、保存している各ドキュメントの最後の操作のシーケンス番号とプライマリタームを追跡します。シーケンス番号とプライマリタームは、GET APIの応答の_seq_noおよび_primary_termフィールドに返されます:

Python

  1. resp = client.get(
  2. index="products",
  3. id="1567",
  4. )
  5. print(resp)

Ruby

  1. response = client.get(
  2. index: 'products',
  3. id: 1567
  4. )
  5. puts response

Js

  1. const response = await client.get({
  2. index: "products",
  3. id: 1567,
  4. });
  5. console.log(response);

コンソール

  1. GET products/_doc/1567

返される:

コンソール-結果

  1. {
  2. "_index": "products",
  3. "_id": "1567",
  4. "_version": 1,
  5. "_seq_no": 362,
  6. "_primary_term": 2,
  7. "found": true,
  8. "_source": {
  9. "product": "r2d2",
  10. "details": "A resourceful astromech droid"
  11. }
  12. }

注: Search APIは、seq_no_primary_termパラメータを設定することで、各検索ヒットの_seq_noおよび_primary_termを返すことができます。

シーケンス番号とプライマリタームは、変更を一意に識別します。返されたシーケンス番号とプライマリタームを記録することで、取得した後に他の変更が行われていない場合にのみドキュメントを変更することができます。これは、index APIupdate API、またはdelete APIif_seq_noおよびif_primary_termパラメータを設定することで行われます。

たとえば、次のインデックス作成呼び出しは、他のAPIによる説明の変更や別のタグの追加を失うことなく、ドキュメントにタグを追加することを保証します:

Python

  1. resp = client.index(
  2. index="products",
  3. id="1567",
  4. if_seq_no="362",
  5. if_primary_term="2",
  6. document={
  7. "product": "r2d2",
  8. "details": "A resourceful astromech droid",
  9. "tags": [
  10. "droid"
  11. ]
  12. },
  13. )
  14. print(resp)

Js

  1. const response = await client.index({
  2. index: "products",
  3. id: 1567,
  4. if_seq_no: 362,
  5. if_primary_term: 2,
  6. document: {
  7. product: "r2d2",
  8. details: "A resourceful astromech droid",
  9. tags: ["droid"],
  10. },
  11. });
  12. console.log(response);

コンソール

  1. PUT products/_doc/1567?if_seq_no=362&if_primary_term=2
  2. {
  3. "product": "r2d2",
  4. "details": "A resourceful astromech droid",
  5. "tags": [ "droid" ]
  6. }