# 機能設計書 61-リモートストア

## 概要

本ドキュメントは、OpenSearchのリモートストア機能に関する機能設計書である。リモートストア機能は、インデックスデータ（Luceneセグメント）およびトランスログをリモートストレージ（S3、Azure Blob Storage等）に永続化する機能であり、ノード障害時のデータ耐久性向上とシャードリカバリの高速化を実現する。

### 本機能の処理概要

**業務上の目的・背景**：従来のOpenSearchではインデックスデータはローカルディスクに保存され、ノード障害時にはピアリカバリによるデータ復旧が必要であった。リモートストアは、セグメントやトランスログをリモートストレージに非同期でアップロードすることで、データの永続性を確保し、リカバリ時間を大幅に短縮する。

**機能の利用シーン**：高可用性が求められる本番環境において、ノード障害やゾーン障害が発生した場合にデータロスを防止し、迅速なリカバリを行うために利用される。また、リモートストアバックドインデックスへの移行（Mixed Mode / Strict Mode）にも利用される。

**主要な処理内容**：
1. Luceneセグメントデータのリモートストレージへの非同期アップロード
2. トランスログのリモートストレージへの非同期アップロード
3. リモートストアからのデータのダウンロード・リストア
4. バックプレッシャー制御（アップロードの遅延監視とリクエスト拒否）
5. リモートストアパス戦略の管理（FIXED / HASHED_PREFIX / HASHED_INFIX）
6. 転送統計の追跡と監視

**関連システム・外部連携**：Amazon S3、Azure Blob Storage、Google Cloud Storage等のリモートストレージサービスと連携する。BlobStoreRepositoryを通じて抽象化されたBlobStore APIを使用する。

**権限による制御**：クラスタレベルの設定（`cluster.remote_store.enabled`）により有効化が制御される。インデックス作成時にリモートストア設定を適用するにはインデックス作成権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 126 | リモートストアリストア | 主機能 | リモートストアからリストアする処理 |
| 127 | リモートストア統計 | 主機能 | リモートストアの統計情報を返す処理 |

## 機能種別

データ永続化・レプリケーション / データ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cluster.remote_store.enabled | boolean | No | リモートストアの有効化フラグ | true/false |
| cluster.remote_store.segment.repository | String | Yes (有効時) | セグメント用リモートリポジトリ名 | 登録済みリポジトリであること |
| cluster.remote_store.translog.repository | String | Yes (有効時) | トランスログ用リモートリポジトリ名 | 登録済みリポジトリであること |
| cluster.remote_store.segment.pressure.enabled | boolean | No | バックプレッシャー有効化フラグ | true/false |
| cluster.remote_store.segment.pressure.bytes_lag.variance_factor | double | No | バイトラグの分散係数 | 正の数値 |
| cluster.remote_store.segment.pressure.time_lag.variance_factor | double | No | タイムラグの分散係数 | 正の数値 |
| cluster.remote_store.segment.pressure.consecutive_failures.limit | int | No | 連続失敗回数の閾値 | 正の整数 |

### 入力データソース

ノードの設定ファイル（opensearch.yml）、クラスタ動的設定（Cluster Update Settings API）、インデックス設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| RemoteSegmentStats | Object | リモートセグメント転送の統計情報（アップロードバイト数、ダウンロードバイト数、失敗回数等） |
| RemoteTranslogTransferTracker | Object | トランスログ転送の追跡情報 |
| RemoteStoreStatsResponse | Object | ノードレベルのリモートストア統計 |

### 出力先

リモートストレージ（S3、Azure Blob Storage、GCS等）、REST API レスポンス（統計情報取得時）

## 処理フロー

### 処理シーケンス

```
1. インデックス作成時にリモートストア設定を付与
   └─ RemoteStoreCustomMetadataResolverがパス戦略・ハッシュアルゴリズムを決定
2. ドキュメント書き込み時にLuceneセグメントが生成される
   └─ ローカルディスクにセグメントが書き込まれる
3. リフレッシュ操作でセグメントが確定
   └─ RemoteSegmentTransferTrackerが転送対象を追跡
4. バックグラウンドでリモートストレージへアップロード
   └─ BlobStoreTransferServiceを通じてセグメントデータをアップロード
5. バックプレッシャー検証
   └─ RemoteStorePressureServiceがラグを検証し、閾値超過時にリクエストを拒否
6. トランスログも同様にリモートストレージへアップロード
   └─ RemoteTranslogTransferTrackerが転送を追跡
```

### フローチャート

```mermaid
flowchart TD
    A[ドキュメント書き込み] --> B[ローカルセグメント生成]
    B --> C[リフレッシュ操作]
    C --> D{リモートストア有効?}
    D -->|No| E[通常処理完了]
    D -->|Yes| F[セグメント転送キュー追加]
    F --> G[バックプレッシャー検証]
    G -->|ラグ超過| H[リクエスト拒否]
    G -->|OK| I[リモートストレージへアップロード]
    I --> J{アップロード成功?}
    J -->|Yes| K[統計情報更新]
    J -->|No| L[失敗カウント更新・リトライ]
    L --> I
    K --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-61-01 | バイトラグ検証 | アップロードバイト移動平均 * 分散係数を超過するバイトラグがある場合、書き込みリクエストを拒否 | バックプレッシャー有効かつRefreshSeqNoLag > 1 |
| BR-61-02 | タイムラグ検証 | アップロード時間移動平均 * 分散係数を超過するタイムラグがある場合、書き込みリクエストを拒否 | バックプレッシャー有効かつRefreshSeqNoLag > 1 |
| BR-61-03 | 連続失敗検証 | 連続失敗回数が閾値を超過した場合、書き込みリクエストを拒否 | バックプレッシャー有効時 |
| BR-61-04 | パス戦略互換性 | HASHED_PREFIX/HASHED_INFIXパスタイプにはハッシュアルゴリズムが必須 | インデックス作成時 |

### 計算ロジック

バックプレッシャーの動的閾値算出:
- `dynamicBytesLagThreshold = uploadBytesMovingAverage * bytesLagVarianceFactor`
- `dynamicTimeLagThreshold = uploadTimeMovingAverage * uploadTimeLagVarianceFactor`

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| セグメントアップロード | リモートBlobStore | WRITE | Luceneセグメントデータのアップロード |
| セグメントダウンロード | リモートBlobStore | READ | リストア時のセグメントデータダウンロード |
| トランスログアップロード | リモートBlobStore | WRITE | トランスログデータのアップロード |
| メタデータ更新 | クラスタメタデータ | UPDATE | リモートストア設定のインデックスメタデータへの保存 |

### テーブル別操作詳細

#### リモートBlobStore

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| WRITE | segments/{indexUUID}/{shardId}/data | Luceneセグメントファイル | パス戦略に基づくパス生成 |
| WRITE | translog/{indexUUID}/{shardId}/data | トランスログファイル | パス戦略に基づくパス生成 |
| READ | segments/{indexUUID}/{shardId}/metadata | セグメントメタデータ | リストア時に使用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| OpenSearchRejectedExecutionException | バックプレッシャー拒否 | バイトラグ/タイムラグ/連続失敗が閾値超過 | クライアント側でリトライ |
| RepositoryException | リポジトリエラー | リモートストレージへの接続失敗 | リポジトリ設定の確認 |
| IllegalArgumentException | パラメータエラー | 互換性のないPathTypeとHashAlgorithmの組み合わせ | 正しいパス戦略設定の指定 |

### リトライ仕様

セグメント・トランスログのアップロード失敗時は、バックグラウンドタスクで自動リトライされる。連続失敗数がRemoteStorePressureSettingsの閾値を超えると新規書き込みリクエストが拒否される。

## トランザクション仕様

リモートストアへのアップロードは非同期で行われるため、トランザクション管理はローカルのLuceneインデックス操作とは独立している。セグメントのアップロードはリフレッシュごとにバッチ処理され、アトミックな操作ではない。

## パフォーマンス要件

- セグメントアップロードはバックグラウンドスレッドで非同期実行
- 移動平均ベースのバックプレッシャーにより、アップロード遅延時に書き込みスループットを自動調整
- ハッシュベースパス戦略（HASHED_PREFIX/HASHED_INFIX）によりリモートストレージのホットスポットを回避

## セキュリティ考慮事項

- リモートストレージへのアクセスはリポジトリ設定で管理される認証情報（AWS Credentials、Azure SAS Token等）を使用
- セキュアな通信プロトコル（HTTPS）を使用すべき
- リモートストア設定はクラスタレベル設定であり、クラスタ管理者権限が必要

## 備考

- リモートストアはExperimental API（@ExperimentalApi）として提供されており、将来のバージョンで変更される可能性がある
- FNV-1aハッシュアルゴリズムを使用したパスハッシュ（FNV_1A_BASE64, FNV_1A_COMPOSITE_1）をサポート
- データカテゴリにはSEGMENTSとTRANSLOGがあり、それぞれDATA、METADATA、LOCK_FILESのデータタイプを持つ

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、リモートストアで使用されるデータカテゴリ・パス戦略・ハッシュアルゴリズムの列挙型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RemoteStoreEnums.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreEnums.java` | DataCategory（SEGMENTS, TRANSLOG）、DataType（DATA, METADATA, LOCK_FILES）、PathType（FIXED, HASHED_PREFIX, HASHED_INFIX）、PathHashAlgorithm（FNV_1A_BASE64, FNV_1A_COMPOSITE_1）の4つの列挙型を理解する |
| 1-2 | RemoteStorePathStrategy.java | `server/src/main/java/org/opensearch/index/remote/RemoteStorePathStrategy.java` | PathInput、ShardDataPathInput、SnapshotShardPathInputのデータクラスとパス生成ロジック |
| 1-3 | RemoteIndexPath.java | `server/src/main/java/org/opensearch/index/remote/RemoteIndexPath.java` | リモートインデックスパスのメタデータモデル |

**読解のコツ**: RemoteStoreEnumsのPathType列挙型はそれぞれgeneratePathメソッドを持ち、Strategy Patternで実装されている。FIXED型はハッシュアルゴリズム不要、HASHED_PREFIX/HASHED_INFIXはハッシュアルゴリズム必須である点に注意。

#### Step 2: エントリーポイントを理解する

バックプレッシャー制御のサービスクラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RemoteStorePressureService.java | `server/src/main/java/org/opensearch/index/remote/RemoteStorePressureService.java` | バックプレッシャー制御の全体構造。3つのLagValidator（ConsecutiveFailureValidator, BytesLagValidator, TimeLagValidator）の検証ロジック |

**主要処理フロー**:
1. **61-62行目**: `isSegmentsUploadBackpressureEnabled()`でバックプレッシャー有効かチェック
2. **70-86行目**: `validateSegmentsUploadLag()`で3つのバリデータを順に実行し、失敗時にOpenSearchRejectedExecutionExceptionをスロー
3. **134-144行目**: BytesLagValidatorの`validate()`でバイトラグ閾値を動的算出
4. **180-191行目**: TimeLagValidatorの`validate()`でタイムラグ閾値を動的算出
5. **227-230行目**: ConsecutiveFailureValidatorの`validate()`で連続失敗回数を検証

#### Step 3: 統計追跡を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RemoteSegmentTransferTracker.java | `server/src/main/java/org/opensearch/index/remote/RemoteSegmentTransferTracker.java` | セグメント転送の統計情報（バイトラグ、タイムラグ、移動平均等）の追跡 |
| 3-2 | RemoteTranslogTransferTracker.java | `server/src/main/java/org/opensearch/index/remote/RemoteTranslogTransferTracker.java` | トランスログ転送の統計情報の追跡 |
| 3-3 | RemoteStoreStatsTrackerFactory.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreStatsTrackerFactory.java` | トラッカーのファクトリ |

#### Step 4: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RemoteStoreUtils.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreUtils.java` | long値の反転、Base64エンコーディング、セグメント名抽出等のユーティリティメソッド |

### プログラム呼び出し階層図

```
IndexShard (書き込み操作)
    |
    +-- RemoteStorePressureService.validateSegmentsUploadLag()
    |       |
    |       +-- ConsecutiveFailureValidator.validate()
    |       +-- BytesLagValidator.validate()
    |       +-- TimeLagValidator.validate()
    |
    +-- RemoteStoreStatsTrackerFactory
    |       |
    |       +-- RemoteSegmentTransferTracker
    |       +-- RemoteTranslogTransferTracker
    |
    +-- BlobStoreTransferService (セグメント/トランスログ転送)
    |       |
    |       +-- BlobStore.writeBlob() / BlobStore.readBlob()
    |
    +-- RemoteStorePathStrategy.generatePath()
            |
            +-- PathType.generatePath() + PathHashAlgorithm.hash()
```

### データフロー図

```
[入力]                          [処理]                              [出力]

ドキュメント書き込み ──> IndexShard ──> ローカルLuceneセグメント ──> ローカルディスク
                                  |
                                  +──> RemoteStorePressureService ──> 拒否/許可判定
                                  |
                                  +──> BlobStoreTransferService ──> リモートBlobStore
                                          |                           (S3/Azure/GCS)
                                          +──> RemoteSegmentTransferTracker ──> 統計情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RemoteStoreEnums.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreEnums.java` | ソース | データカテゴリ・タイプ・パスタイプ・ハッシュアルゴリズムの列挙型定義 |
| RemoteStorePathStrategy.java | `server/src/main/java/org/opensearch/index/remote/RemoteStorePathStrategy.java` | ソース | リモートストアパス生成戦略 |
| RemoteStorePressureService.java | `server/src/main/java/org/opensearch/index/remote/RemoteStorePressureService.java` | ソース | バックプレッシャー制御サービス |
| RemoteStorePressureSettings.java | `server/src/main/java/org/opensearch/index/remote/RemoteStorePressureSettings.java` | ソース | バックプレッシャー設定 |
| RemoteSegmentTransferTracker.java | `server/src/main/java/org/opensearch/index/remote/RemoteSegmentTransferTracker.java` | ソース | セグメント転送統計追跡 |
| RemoteTranslogTransferTracker.java | `server/src/main/java/org/opensearch/index/remote/RemoteTranslogTransferTracker.java` | ソース | トランスログ転送統計追跡 |
| RemoteStoreStatsTrackerFactory.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreStatsTrackerFactory.java` | ソース | トラッカーファクトリ |
| RemoteStoreUtils.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreUtils.java` | ソース | ユーティリティメソッド |
| RemoteIndexPath.java | `server/src/main/java/org/opensearch/index/remote/RemoteIndexPath.java` | ソース | リモートインデックスパスモデル |
| RemoteIndexPathUploader.java | `server/src/main/java/org/opensearch/index/remote/RemoteIndexPathUploader.java` | ソース | リモートインデックスパスのアップロード |
| RemoteStoreCustomMetadataResolver.java | `server/src/main/java/org/opensearch/index/remote/RemoteStoreCustomMetadataResolver.java` | ソース | カスタムメタデータ解決 |
| RemoteMigrationIndexMetadataUpdater.java | `server/src/main/java/org/opensearch/index/remote/RemoteMigrationIndexMetadataUpdater.java` | ソース | リモートストア移行時のメタデータ更新 |
| RemoteSegmentStats.java | `server/src/main/java/org/opensearch/index/remote/RemoteSegmentStats.java` | ソース | セグメント統計データモデル |
| RemoteTransferTracker.java | `server/src/main/java/org/opensearch/index/remote/RemoteTransferTracker.java` | ソース | 転送追跡の基底クラス |
