kevy4.0

kevyの上にアプリケーションを設計する

kevyはサービングエンジンです。ふだんなら業務モデルをリレーショナルデータベースに載せ、その手前にキャッシュを置く——そういうアプリケーションのための、一次データストアです。このページはその地図にあたります。エンジンが何を提供し、どんな法がそれを境界づけ、どの能力がどこに住んでいるのかを示します。

RDSからの移行を考えているなら、まずこのページを読み、そのうえでクックブックのレシピを1つずつ辿ってください。

7つのプレーン

プレーン何を運ぶか場所
P0 — 操作あらゆる面のあらゆるop。サーバー(RESP)、組み込み(プロセス内)、Lua、アトミックブロック、パイプライン。OP_TABLEは1つで、パリティはCIが強制する。docs/verb-reference.md
P1 — アトミック性と耐久性シングルシャードのアトミックブロック、決定論的順序の全シャードブロック、appendfsync × アトミックコミットのマトリクス、ブロック単位のfsyncバリア。docs/persistence.md
P2 — インデックス宣言型のセカンダリインデックス、4種類(rangeuniquetext(CJK bigram + BM25)、ann(HNSW))。構成上の派生物(書き込みフックで維持され、ドリフトはゼロ)、ワンホップのhydration(FIELDS)、バックフィルによる再構築。docs/indexes.md、docs/text-search.md、docs/vector-search.md
P3 — ビューと代数インデックス上の名前付き合成(virtual / materialized top-K)、Redisセマンティクスをそのまま持つzset/set代数。docs/views.md
P4 — フロー(generation, offset)カーソルを持つCDCフィード(組み込みのoutbox)、ブロッキングpop、ハッシュフィールドTTL、スナップショット読み出しビュー、組み込みの読み取り専用RESPリスナー。docs/cdc.md、docs/embedded-listener.md
P5 — 証拠宣言した行はすべて計測され、突き合わされる。クラッシュ整合性のカオスゲート、30Mキーの混在スタックsoak。bench/VALIDATION-LEDGER.md
P6 — 可用性ackされたオフセットの真実とハートビートを持つレプリケーション、計画的なハンドオーバー(FAILOVER)とクラッシュフェイルオーバー(クォーラム選挙、選挙のみが書き込み権限を与える、フォークの破棄)、そしてオプトインの整合性ラダー(WAIT、read-your-writesトークン(REPL.TOKEN/REPL.WAIT)、有界ステイルネス(-STALE)、クォーラムリースによる書き込みフェンス)。13個の実行可能なclamp(availgate)がCIで走る。docs/availability.md、docs/replication.md

3つの法

kevyが「出来の悪いRDS」へ滑り落ちるのを防いできた——そしてこれからも防ぐ——憲法です。

法1 — Redisの契約は不可侵である。 kevyが実装するRedisのopは、すべてRedisとまったく同じように振る舞います。新ジャンルの能力が既存verbのセマンティクスを変えることはなく、内部キー空間がSCAN/KEYS/DBSIZEに漏れることもなく、それらは自分専用のコマンド名前空間(IDX.*VIEW.*FEED.*PREFIX.*)に住みます。

法2 — スーパーセットはエンジンのジャンルに属するときだけ。 ある能力が採用されるのは、それがエンジン自身の持てるライフサイクル——宣言する → 維持する → 検証する → 再構築する——を備えた派生データであるときだけです。インデックス、ビュー、フィード、ダイジェストはすべてこのテストを通ります。アプリのロジックを蓄えることは通りません。

法3 — RDSの事象の地平線。 クエリ言語なし、プランナなし、JOINなし、サーバーサイドのバリデーションなし、トリガーなし。エンジンが「宣言されたアクセスパスを*実行する*」のをやめて「問いへの答え方を*決める*」ようになった瞬間、それはRDSです——それも、出来の悪いRDSです。kevyは恒久的にこの地平線の手前にとどまります。

検討したうえで断ったもの

以下はどれも、必要そのものは本物です。ただし機能の形が間違っている——そして、それぞれに手当ての答えがあります。

こう求めたくなるかもしれない代わりに使うもの
SQL / クエリDSL明示的なインデックスAPI + クックブック
クエリプランナ / 自動インデックス選択IDX.EXPLAIN(診断専用)
JOINワンホップのhydration(FIELDSVIA)+ アプリ側での組み立て
外部キー / カスケードアトミックブロック、プレフィックス一括操作、CDCコンシューマ
CHECK制約アトミックブロック内での読み出し(アプリが判定し、エンジンがアトミックにコミットする)
スキーマ / 型付きカラムバイト列はあなたのもの。型はインデックス作成時に宣言する
JSONパスクエリハッシュフィールドこそがカラムモデルである
トリガー / 書き込みパスのUDFCDCコンシューマ——コミット後、疎結合、リプレイ可能
GROUP BY / 集約パイプライン自分のモデルの中で、書き込み時に集約を維持する
タイムトラベルスナップショット + CDCの保持期間(recovery-point契約)
トランザクショナルoutbox不要——フィードがoutboxそのものである
インデックスなしのWHERE意図的に存在しない。アクセスパスをモデル化するか、そのクエリを出さないか

サービング憲章(恒久的にゲートされるもの)

数値はラチェットです。床は上がることしかありません。定常ライン(計測値はbench/VALIDATION-LEDGER.md)は次のとおりです。

どこから始めるか

  1. プレフィックスとアクセスパスをモデル化する(クックブック §1-2)。
  2. バルクロードし、そのあとインデックスを宣言する(移行ガイド)。
  3. ホットなリスト向けにビューを合成する(ビュー)。
  4. イベントコンシューマをフィードに配線する(CDC)。
  5. ダイジェストで検証し、ゲートを見張る。
  6. 1ノードでは足りなくなったら、レプリカを足し、整合性ラダーのどの段に乗るかを選ぶ(可用性)。