要点: 検索インデックスは高速な読み取り用モデルであり、正のデータから再構築できなければなりません。
この記事の用語: インデックス:検索用データ構造。Reindex:インデックス全体を再構築すること。検索適合度:検索結果の適合度。
現場の課題
書き込み処理の中でインデックスを更新すると利用者を待たせ、失敗時には変更を失います。共有インデックスには越境リスクがあり、構造変更時には検索を止めずに新版へ移す仕組みが必要です。
単純な対策だけでは不十分な理由
検索インデックスは再構築可能な読み取りモデルであり、正のデータではありません。ドキュメントにテナントと元データのバージョンを持たせ、新インデックスを並行構築してエイリアスで切り替えます。
処理フロー
Authoritative Change→Outbox・CDC
永続イベント→Indexer
バージョン 変換処理→検索インデックス
テナント 読み取りモデル
アーキテクチャ上の判断
Versioned ドキュメント
遅延イベントの上書きを防ぎます。
スキーマとエイリアス分離
Immutable インデックス バージョンを使います。
オフライン・Online評価
Precision、Recall、成功Outcomeを測ります。
さらに深く考える
DeletionをFirst-種別化
Primary、インデックス、キャッシュ、バックアップをポリシー通り処理します。
Rebuild 処理能力がResilience
復旧 Objective内でFull Rebuildを試験します。
実装手順
- 確定済み変更をOutboxまたはCDCで取得し、利用者向けトランザクション内でインデックス更新しません。
- 各ドキュメントへサーバー管理のテナントIDと元データのバージョンを持たせます。
- 新インデックスを並行構築・検証し、エイリアスを原子的に切り替えます。
コード例: エイリアス-based Reindex
create index products_v3(mapping_v3)
bulk index snapshot with sourceVersion
consume changes after snapshot watermark
compare counts, samples and query set
atomic alias products_read: v2 -> v3ロールバック Window中は旧インデックスもFeedします。
想定しておく障害
- 遅延Updateが削除データを復活させます。
- テナント Filter漏れが越境します。
- Reindexがソースコード DBを飽和させます。
監視すべきこと
| 指標 | 何が分かるか |
|---|---|
| インデックス Lag | データの新しさを測ります。 |
| Stale バージョン Reject | Out-of-order封じ込めです。 |
| Zero-result・Success率 | 利用者 Outcomeで検索適合度を測ります。 |
設計の検証方法
- Update・Delete イベントを遅延・逆順にします。
- Cross-テナント Negative クエリを実行します。
- 書き込み中にFull Reindexします。
本番導入の進め方
既存インデックスへ永続イベントとドキュメント バージョンを追加します。代表クエリで新版を比較し、少数テナントをエイリアス経由で切り替えてから全体へ広げます。
本番前チェックリスト
- Searchをトランザクションの正のデータにしません。
- Delete Propagationを測ります。
- 固定クエリ Setで検索適合度を評価します。
まとめ
信頼できる検索は、再構築可能なデータ、明示したデータの新しさ、実クエリで測る検索適合度を持ちます。
