このページ
5.0 から 5.1 へのアップグレード
短く言うと:5.0 のサーバーを停止し、同じデータディレクトリで 5.1 のバイナリを起動するだけです。設定変更もワイヤ変更もクライアント 変更も不要。リリースゲートはタグを打つ前に、この手順を両方向で—— バージョン混在の primary/replica ペアも含めて——毎回再演します。
圧縮や value log を使っているなら、早めに上げてください。 5.0 の エンコーダは、5.0 自身のデコーダが受け付けないフレームを書きうるから です(コンパクション後、コールドな値が corrupt として読み戻る)。5.1 はエンコーダを直したうえで、5.0 がすでにディスクに書いてしまった フレームを救出します。詳細は下記。
このリリースが存在する理由
- 5.0 の読み出しハザードを修復。 辞書が共有 Huffman テーブルを 運んでいるとき、
kevy-compressはリテラルのみのフレームを「辞書 マッチを使った」かのようにタグ付けすることがありました。書き込み 時には何も検出できず(CRC は書いたバイト列に対するもの)、障害は 後になって、コンパクション経路で、正常に保存されたはずの値のデコ ードエラーとして表面化します。5.1 はタグを修正し、さらに 5.0 が すでに書いた誤タグのフレームをデコードする明示的な互換アームを 追加しました。5.1 が書いたフレームは 5.0 でも読めます。 - 巨大コレクションがシャードを止めなくなった。 list・hash・set・ sorted-set は約 1.6 万要素を超えると要素粒度のコピーオンライトに なります。rewrite やスナップショットが値を固定している間の書き込み は、1 セグメント(約 1 ミリ秒、コレクション総サイズに依存しない) だけをクローンします。従来は値全体で 0.35〜9.5 秒かかり、その コレクションの常駐メモリを一時的に倍にしていました。
appendfsync alwaysが reactor を止めなくなった。 両方の reactor がグループコミットします:io_uring では応答を fsync 完了で ゲートし、epoll/kqueue ではシャードごとの writer レーンが同じことを します。ext4・50 並行接続での実測は、io_uring で 353 → 8,273 writes/s、epoll で 478 → 10,540。耐久性の契約は不変です——応答は 依然として「ディスクに載った」を意味します。- フェイルオーバーの収束を修正。 新しく昇格した primary に切り 替えた replica が、接続したまま永久に何も受け取らないことがあり ました:link は up、ハートビートは流れ、resync も進行中でないのに、 フェイルオーバー後の書き込みが届かない。下の複製の節を参照。
ストアを組み込んでいる場合
サーバーを動かすのではなく kevy-embedded をリンクしているなら、この ページの大半はあなたが持っていない機構の話です。ある組み込み利用者の 呼び出し面は全体で Config::default().with_persist(dir) と Store::open、 get / set / del / keys だけでした——その形なら、アップグレードは 2 つの問いに尽きます。
5.1 は 5.0 が書いたものを読めるか。読めます。そのあと 5.0 は 5.1 が 書いたものを読めるか。読めます。 サーバー側の経路から推論したのでは なく、公開済みクレートで実測しました:5.0.0 の組み込みストアが 201 キー (うち 1 つは 200 KB なので大きい値の経路も含まれます)を書いて AOF を リライトし、5.1.0 がそのディレクトリを開いて 201 件すべて読み戻し、 5.1.0 が自分の 201 件を追記し、5.0.0 がその結果を開き直して 402 件 すべて読み戻しました。両方向とも clean な replay で、同じプログラムが どちらのバージョンに対しても無改造でコンパイルできます。
このページの残りはサーバーの機構です。プロセス内には reactor も io_uring も複製もリスナーもないので、次のものはあなたにとって意味を 持ちません:KEVY_AOF_OFFLOAD、appendfsync always のグループコミット、 スナップショット resync とその -LOADING 窓、feed の generation、 --accept-shards、そして上に挙げたテールレイテンシの数値すべて。
届くもの:圧縮の修正——ただし圧縮または value log を有効にしていた 場合のみ(Config::default() では有効になりません)——と、約 1.6 万 要素を超えるコレクションの要素粒度コピーオンライト。後者は rewrite_aof() が書き込みに課しうる停止時間を短くします。
そのまま引き継がれるもの
- データファイル。 5.1 は 5.0 のディレクトリをそのまま開き、5.0 も 5.1 が最後に書いたディレクトリを開き直せます(両方向ともゲート 済み)。どちらに切り替える場合もクリーンシャットダウンしてから。
- ワイヤプロトコル・コマンド・クライアント契約。 削除も型変更も ありません。既存クライアントは変更もリビルドも不要です。
- 設定ファイルとフラグ。 5.0 のキーはすべて、同じデフォルトで 受け付けられます。
振る舞いが変わるもの
再接続した replica は 1 回スナップショット resync する
複製カーソルが継続性を主張できない replica——retarget、REPLICAOF、 あるいは feed の generation が動くバージョン変更のあとの状態——には、 現在のオフセット空間の先頭からの再生ではなく、フルスナップショット で答えるようになりました。primary から中身が見えない replica を収束 させる唯一の答えがこれだからです:フレームの列はキーを追加・上書き できても、replica が持っていて primary が持たないキーを削除できません。
アップグレード後の最初の接続で、シャードごとに一度だけ次が見えます:
kevy: replica fd 42 generation 6843605247850762 != feed generation
4198793490690396 (sent_offset 0); shipping snapshotこれは想定どおりで、自己修復します。同時に、replica のローカルな 分岐は持ち越されずに破棄される、という分岐履歴に対する文書化済みの 契約でもあります。
その resync が着地するまでのあいだ、replica は読み取りに -LOADING を返します——これは従来からフル resync で同じでした。キー空間が置き 換えられている最中であり、一貫した答えが存在しないからです。PING は例外のままです。窓の長さはデータセット次第なので、この間の読み取り 不可を許容できない場合は、再起動の前にその replica を読み取りプール から外してください。
これが閉じるバグ:昇格は選挙が決着した瞬間に書き込みを開放しますが、 各シャードは自分の tick で複製オフセットをフェンスします。その窓の なかで受理された書き込みはフェンスに破棄され、あとから接続した replica は「すでに追いついている」と告げられます——結果、その書き込み は primary のキー空間には存在するのにどのストリームにも存在せず、 リンクは完璧に健全だと報告し続けます。
appendfsync always は fsync ラウンドを共有する
always では、並行接続がそれぞれ自分の fsync を払うのではなく、 fsync ラウンドを共有(グループコミット)します。逐次実行の単一 クライアントは少し遅くなり——インラインの fsync ではなくキューされた fsync とその完了を待つため——並行負荷では桁違いに速くなります。 従来の形が必要なら、KEVY_AOF_OFFLOAD=0 がどちらの reactor でも 古典的な同期パスを復元します。
feed の generation はランダムな識別子になった
feed の generation はカウンタではなくランダムな 53 ビットの履歴識別子 になりました。2 つのノードが異なる履歴を同じ名前で呼ぶことは、もはや ありえません。generation を表示・保存していたもの(REPL.TOKEN、 REPL.WAIT、FEED.TAIL)は、大きく順序のない数値を示します。これは 識別子です:等値比較のみに使い、大小比較には決して使わないでください。
推奨手順
- バックアップを取る:クリーンシャットダウン(または
BGSAVE+ コピー)してから、データディレクトリをコピーします。 - replica を先に、primary をあとにアップグレードします。混在ペアは 両方向で動作し、各 replica はカーソルの generation が一致しなく なった時点で一度だけ resync します。
- 検証:各 replica の
INFO replication(link up、オフセットが前進)、INFO persistence、期待値に対するDBSIZE、そしてアプリケーション 自身のスモークテスト。 - 必要ならロールバック:5.1 をクリーンに停止し、同じディレクトリで 5.0 を起動します。5.1 が書いた値はそのまま読めます。