kevy
このページ

以前のメジャーバージョンのアップグレード

章は2つ、新しいものから。3.x → 4.0(APIの定義に関するメジャー。クライアントワイヤはそのまま、ディスクは無変更で開いて最初のリライトでフォーマットが昇格し、Rustの顔は一度だけ変わって、以後は凍結されます)と、2.x → 3.x(能力のメジャー。すべてが引き継がれました)です。各章は、何が自動でアップグレードされ、何にコード変更が要り、そしてどう戻すのかを明示します。

6.2 から来た方へ。 そのホップはこのページではなく upgrading-6.2-to-6.3.md です。


3.x → 4.0

4.0は「産業運用に耐える」という宣言です。semverのメジャーは意図的に使いました——長年たまってきた公開APIの負債をすべて払うための、1回きりの破壊の窓です。そしてこれ以降、各面は凍結されます。以後の4.xリリースは追加のみです。ワイヤ越しにkevyと話しているなら、4.0はバイナリの差し替えです。kevyのcrateをリンクしているなら、短く機械的な移行を見込んでください——以下の変更にはどれも、1行のルールがあります。

TL;DR —— バージョンの一覧

コンポーネント3.x時代4.0やること
kevy(サーバー)3.18.x4.0.0バイナリを差し替え、同じデータディレクトリで再起動する
kevy-embedded3.18.x4.0.0バージョンを上げ、下のAPI表を適用する
kevy-client1.14.x2.0.0バージョンを上げる —— 2つのクライアントは独自のバージョン線を保ち、今回の破壊的変更に対応するのが2.0.0です + API表
kevy-client-async1.1.x2.0.0同上
kevy-wasm / @goliapkg/kevy(npm)4.0.04.0での新顔 —— docs/wasm.md
インフラcrate(kevy-storekevy-rt、…)3.18.x4.0.0ワークスペースのバージョンに追従する

kevy-clientkevy-client-asyncはワークスペースのバージョン線に乗っていません。出荷されるのは2.0.0であり、4.0.0ではありません。cargo add kevy-clientが2.xを解決するのは、それが最新版だからです(古い版ではありません)。(6.2.1 まではそうでした。以降、両クライアントはワークスペースのバージョンに揃い、"2" の要求は 5.x エンジンに対して組まれたクライアントに解決されます——upgrading-6.2.0-to-6.2.1.md を参照。)

自動で互換なもの

ワイヤプロトコル。 RESPは変わっておらず、verbのエイリアス(SLAVEOFHMSET、…)もすべて保たれています。Redisのクライアント、スクリプト、redis-cliのセッションは以前どおり動きます。valkey 9.1に対する応答パリティのスイートは、今もCIのゲートです。

レプリケーションワイヤ(kevy ↔ kevy)——ひとつのクリーンな断絶。 内部のレプリケーションハンドシェイクはfeed generationを運ぶようになりました(REPLICATE FROM <gen> <offset> ID <id> / +ACK <gen> <offset>)——プライマリのuncleanな再起動をまたいでもoffset再開要求を安全にする、あのフェンスです。4.0のレプリカは3.xのプライマリとハンドシェイクできず、逆も同様です。レプリケーションペアの両端は同じ窓で揃えて上げてください(レプリカが先、プライマリが後、がダウンタイム最小の順——新しいプライマリが上がるとレプリカは再接続してフル同期します)。これはkevyの内部プロトコルだけの話で、Redisクライアントに面するものは何も変わっていません。

スナップショットとAOF。 4.0のバイナリは、3.x(および2.x)のスナップショット形式をすべて読み、3.xのAOFを変更なしにリプレイします——3.xのデータディレクトリは移行作業ゼロで開きます。4.0で新しいのはAOFの*レコードフォーマット*(KEVYAOF2:長さ接頭辞 + CRC32Cチェックサム付きレコード——persistence.md参照)で、昇格はファイル単位で遅延的、かつ一方向です:

  • 既存の3.x(KEVYAOF1)ファイルへの追記はv1のまま——バイナリを替えた初日、ファイルは3.18とバイト互換で、ダウングレードはまだバイナリを戻すだけです。
  • 新しいファイルと、最初のリライト(自動リライトまたはBGREWRITEAOF)の出力はv2——3.xには読めません。最初のリライト以降、同じデータディレクトリで3.18へ戻る道はありません(クライアント経由でキー空間をリプレイし直す以外には)。

カナリア期間中に3.18への退路を残したいなら:期間中は自動リライトを止め——サーバーはauto_aof_rewrite_percentage = 0、組み込みはConfig::with_auto_aof_rewrite_disabled()(4.1。3つのトリガーノブを1呼び出しで)——先にスナップショットのバックアップを取ってください。カナリアが定着したら戻すこと。CRCの保護はファイルがv2になって初めて効き始めるので、この状態をカナリアに必要な時間より長く続けないでください。4.1からこの窓は推測ではなく観測可能です:組み込みはStore::downgradeable_to_v3()、サーバーはINFO persistenceaof_format:

AOFに関する注意がひとつ:レガシーなSPOPフレーム。 4.0はSPOPを本当にランダムにし、したがって動詞ではなく*その効果*——SREM key <popped…>、実際に取り除かれたメンバー——をログし(そしてレプリケートし)ます。一度もリライトされていない3.x時代のAOFは、生のSPOPフレームをまだ抱えている可能性があります。それを4.0でリプレイすると新しいランダムな選択が引かれるため、その最初のリプレイ後に残る集合は、アップグレード前のプロセスのものと違いうるのです。集合にSPOPのトラフィックがあるなら、アップグレードの直前か直後に一度BGREWRITEAOFを走らせて現在の状態を実体化してください。それ以降、ログは決定的なフレームだけを運びます。

Config。 3.xのconfigキーはすべて受け入れられ、意味も同じです。2つのキーだけ、*より厳格に、あるいはより誠実に*なりました——下の「振る舞いの変更」を参照してください(notify_keyspace_eventsの未知フラグの拒否、min_replicas_max_lag_msの強制)。

削除されたノブが1つ。 スナップショット/AOFの*ファイル名*のカスタマイズはなくなりました(kevy-embeddedConfig::with_snapshot_filename / with_aof_filenameビルダー)。オンディスクのレイアウトは、シャードごとにdump-{i}.rdb / aof-{i}.aofで固定になりました。デフォルト名で書かれていたディレクトリは——レガシーな単一ファイルのディレクトリも含めて——そのままロードされます。*カスタム*名で書かれたディレクトリだけ、4.0で最初に開く前に、固定の名前へ一度mvする必要があります。

APIの破壊一覧

この節にあるものはすべて、コンパイル時の破壊であり、機械的な修正があります。明示した箇所を除いて、実行時のセマンティクスは変わりません。

1. flush()のshimを削除

非推奨だったエイリアスはなくなりました。生き残った名前は、自分がやること(ストアを消し飛ばすこと)を名乗ります。

Crate削除代わりに呼ぶもの
kevy-embeddedStore::flush()Store::flushall()
kevy-clientConnection::flush()Connection::flushall()
kevy-storeStore::flush()Store::flushall()

2. エラーの通貨を1つに:KevyError

kevy-embeddedkevy-clientの、失敗しうる公開の面はすべて、io::Result<T>ではなくKevyResult<T>Result<T, KevyError>)を返すようになりました。この型はkevy-storeに住み、両方のcrateが再エクスポートしています。

pub enum KevyError {
    Store(StoreError),      // structured engine errors, no longer
                            // flattened into io::Error strings
    Io(std::io::Error),     // real I/O, preserved via From
    Protocol(String),       // server error replies, wire text intact
    ReadOnly,               // replica write rejection
    InvalidInput(String),   // e.g. URL parse errors
    NotFound(String),
    Unsupported(String),    // e.g. remote-only calls on embedded
    TimedOut,               // e.g. Subscription::recv_timeout
    Closed,                 // stream/bus gone; also terminates
                            // subscriber iterators
}

移行はたいてい、戻り値型の注釈を書き換えるだけです——From<io::Error>From<StoreError>があるので、?はそのまま動き続けます。

// 3.x
fn warm(conn: &mut Connection) -> std::io::Result<()> {
    conn.set(b"greeting", b"hello")?;
    Ok(())
}

// 4.0
use kevy_client::{Connection, KevyResult};

fn warm(conn: &mut Connection) -> KevyResult<()> {
    conn.set(b"greeting", b"hello")?;
    Ok(())
}

エラーを*検査していた*コードは、厳密に得をします——文字列をパースするのではなく、バリアントにマッチさせてください。

3.xでのシグナル4.0
io::Error::other("kevy-store: …")のラッパーテキストKevyError::Store(e) —— 構造化されたStoreError
レプリカの書き込み拒否:io::Error::other("READONLY …")KevyError::ReadOnly(そのDisplayは今もREADONLYで始まります)
サーバーの-ERR …応答が、不透明なio::ErrorとしてKevyError::Protocol(text) —— ワイヤのテキストは保存されます
Subscription::recv_timeoutからのErrorKind::TimedOutKevyError::TimedOut
購読ストリームの消失シグナルとしてのErrorKind::UnexpectedEofKevyError::ClosedSubscriberEvents / SubscriberMessagesのイテレータはKevyResult<_>を返し、これで終端します
リモート専用機能に対するErrorKind::UnsupportedKevyError::Unsupported(msg)

4.1から、From<KevyError> for io::Errorは存在します——kind対応づけ(TimedOut → ErrorKind::TimedOutClosed → ConnectionAborted、OOM → OutOfMemory、……)で、しかもsourceを保存します:型つきのKevyErrorio::Errorのsourceとして乗り、ダウンキャストで取り出せるので、境界で何も失われません。4.0はこの逆向きの辺を「損失つきダウングレードの復活」だとして意図的に出荷しませんでした。その後、最初の本番移行がこの変換を約280回、io::Error::other(e)として手書きしました——それこそが損失つきダウングレードであり、しかもkind対応づけを欠いています。orphanルールにより、このimplを提供できるのはkevyだけです。だからkevyが提供します。io::Resultの世界に固定された関数は、いまや?だけで済みます。

移行が実際に何から成るか——それを大規模にやった利用者から:破壊はエラー型がすべてでした——Store::openConfig、各メソッドの形は不変です。機械的なレシピ:自分が所有する可謬シグネチャはKevyResultへ(たいてい注釈だけ。上の例のとおり)、所有していないところは新しいFrom?io::Resultへ運びます。コンパイルエラーを1ページずつ追う代わりに、コンパイラをクエリとして走らせてください——cargo check --message-format=jsonをjqで整形した重複除去済みリストが作業一覧で、その長さが見積もりです。もうひとつ、その利用者が回り道して学んだこと:エラー数は単調ではありません——バイナリcrateは依存ライブラリがコンパイルできて初めて自分の変換エラーを出すので、ループは数までではなく、不動点(何も変わらないパス)まで回してください。

明示的に残した例外がひとつ:CDCフィードのembedded面(changes_tail / changes_since)は自分のFeedErrorを保ちます——ResyncFutureは、このストリーム固有の制御信号であって、汎用のエラーではありません。それらを汎用のエラー列挙に畳み込めば、呼び手が唯一必ず扱わねばならないものを?で通り過ぎるよう誘うことになります。CDCフィードを参照してください。

kevy-resp-clientは意図的にio::Resultの顔を保っています——純粋なトランスポートの石であり、io::Errorこそがその誠実な通貨だからです。)

3. コンストラクタの命名:リソースはopen、ネットワークはconnect

種類ごとに1つのverbを、どこでも。ローカルの、ファイルに裏打ちされたものはopen。ピアを持つものはconnect。純粋にメモリ上の値はnew。改名は次のとおりです。

Crate3.x4.0
kevy-clientConnection::open(url)Connection::connect(url)
kevy-clientSubscriber::open(url, channels)Subscriber::connect_channels(url, channels)
kevy-client-asyncAsyncConnection::open(url)AsyncConnection::connect(url)
kevy-client-asyncAsyncSubscriber::open(url, channels)AsyncSubscriber::connect_channels(url, channels)
kevy-resp-clientRespClient::from_url(url)RespClient::connect_url(url)

すでに準拠していて変更がないもの:kevy_embedded::Store::openkevy_persist::Aof::openkevy_store::Store::newClusterClient::connectRwClient::connectSubscriber::connect(url)RespClient::connect(host, port)

4. kevy_rt::Runtimeは、位置引数ではなくビルダーで組む

位置引数のコンストラクタはなくなりました。Runtimeは自分自身のビルダーです。

// 3.x
let rt = Runtime::new([127, 0, 0, 1], 6004, 4, commands);

// 4.0
let rt = Runtime::builder(commands)
    .bind([127, 0, 0, 1], 6004)
    .shards(4);

builder(commands)のデフォルトは、bindが127.0.0.1:6004、シャード1つ、AOFはオン(EverySec)、データディレクトリは"."です。bind / shardsは、既存のwith_*チェーンと同じく#[must_use]のセッターです。これは4.0のインスタンス化作業の、目に見える顔でもあります。Runtimeはもうグローバル状態に触れないため、1つのプロセスで複数の独立したkevyインスタンスを走らせられます。

5. kevy-storeの書き込みは、借用したargvを取る

所有権を渡す形式は削除され、借用する形式(以前の_borrowedの双子)が正規の名前を引き継ぎました。

3.x(所有)4.0(借用、同じ名前)
del(&[Vec<u8>]) / exists(&[Vec<u8>])del(&[&[u8]]) / exists(&[&[u8]])
hset(&[(Vec<u8>, Vec<u8>)]) / hdel(&[Vec<u8>]) / hmget(&[Vec<u8>])hset(&[(&[u8], &[u8])]) / hdel(&[&[u8]]) / hmget(&[&[u8]])
sadd / srem / lpush / rpush / zrem (&[Vec<u8>])名前は同じで、(&[&[u8]])
zadd(&[(f64, Vec<u8>)])zadd(&[(f64, &[u8])])
zadd_flags_borrowed(…)zadd_flags(…)に改名
// 3.x
store.del(&[b"k1".to_vec(), b"k2".to_vec()]);

// 4.0 — pass slices; no allocation
store.del(&[b"k1".as_slice(), b"k2".as_slice()]);

これはAPI変更の衣を着た性能修正です。kevy-embeddedのファサードは借用したargvをそのまま素通しするようになり、組み込みのすべての書き込みパスにあった、呼び出しごとのto_vec()コピーが消えました。

6. Commandsトレイト + Route(独自コマンドセットを持つ組み込み側)

自分でimpl kevy_rt::Commandsを書いている場合にだけ関係します。

  • dispatch_resp3(Vecを返す形式)を削除 —— dispatch_into_resp3をオーバーライドしてください。
  • wake_idxメソッドを削除 —— 自分のresolve()の中でResolvedCmd::wake_idxを埋めてください。フィールド自体は変わっていません。
  • extension_reduce_v3と、古い2引数のextension_reduceextension_reduce(argv, chunks, proto) -> ExtensionReducedに統合。ExtensionReduced::Reply(bytes)を返すか、古いNUL接頭のin-band継続フレームの代わりにExtensionReduced::Continue(argv2)を返してください。
  • Route::{MGet, SInter, SUnion, SDiff, ZInterCard}Route::Gather(MultiOp)に、Route::{Keys, Scan, RandomKey}Route::Keyspace(KeyShape, Option<Vec<u8>>)に畳み込み。MultiOpKeyShapeは新たにpublicになりました。
  • Commands::on_replication_viewのreplicasエントリが(String, Ipv4Addr, u16, u64, Option<ReplicaAck>)になりました —— 先頭にレプリカidのString、続いてピアの(Ipv4Addr, u16)、送信済みオフセット、そしてReplicaAck { acked_offset, ack_age_ms }(素のackされたオフセットを置き換えます)です。分解して受けてください。

振る舞いの変更(コード変更は不要、運用からは見える)

  • -LOADINGが本物になりました。 レプリカがフル再同期のスナップショットを飲み込んでいるあいだ、読み出しは、半分だけ置き換わったデータセットを返すのではなく-LOADINGを返します。PINGINFOHELLOは答えられるままです(ヘルスチェックは動き続けます)。Redisが免除しているverbと一致します。Redis向けに書かれた「-LOADINGならリトライ」のループは、そのまま正しく動きます。
  • notify_keyspace_eventsが未知のフラグ文字を拒否します。 黙って無視するのではなく、configのパース時に拒否するようになりました——そしてフラグ集合には、本物のx(expired)、e(evicted)、n(new-key)イベントが加わりました。これまでタイポを紛れ込ませていたconfigは、これからは大きな音を立てて失敗します。フラグ文字列を直してください。
  • min-replicas-to-writeは、生きたACKだけを数えます。 min_replicas_max_lag_msというキーは3.xにも存在しましたが、いまや強制されます。最後のACKが窓より古いレプリカは、書き込みゲートを満たさなくなりました。*停滞した*レプリカに頼って書き込みを流し続けていたデプロイには-NOREPLICASが見えるようになります——それこそが、このキーがずっと約束していたセマンティクスです。
  • CLIENTの面が真実を語ります。 CLIENT LISTは本物のコネクションテーブルであり(getpeernameに裏打ちされたアドレス、グローバルに一意なid)、CLIENT KILLは本当にkillし(ブロック中のコネクションも含めて)、CLIENT SETNAMEは定着し、INFOconnected_clientsは生きたゲージです。
  • SHUTDOWNは行儀よくdrainします。 処理中の応答を出し切り、終了前にAOFが最後のfsyncを受けます。素のSIGTERMがsyncされないまま残していた、everysecのテール窓が閉じます。
  • ROLE / INFO replicationがシャードをまたいで集約します。 レプリカごとの識別情報つきです(ip:portと、レプリカごとの真のオフセット)。サーバーごとに要約行が1つ、と仮定していたパーサはそのまま動きます。レプリカごとの行が、より豊かになります。

フィーチャシステム(4.0での新顔)

kevy-embeddedはフィーチャで階層化され、小さなターゲットが使う分だけを支払うようになりました。デフォルトは今までどおり全部入りです。

フィーチャ何が加わるか引き込むもの
coreKV + TTL + pubsub + atomic/pipeline(なし)
persistスナップショット + AOFkevy-persist
index宣言型インデックス + ビューkevy-index
text全文(BM25)のセグメントindexkevy-text
vectorHNSWのANNセグメントindexkevy-vector
replicateレプリケーション + CDCフィードpersistkevy-replicate
listener読み取り専用のRESPリスナー(なし)
tier透過的ティアリング(RAM予算 + コールド値ログ)persistkevy-sys

core階層はmuslターゲット向けにクロスコンパイルでき、強制された予算を持ちます(バイナリ700 KB以下、空ストアのRSS 2 MB以下)。加えて、5つの基盤crateはno_stdでもビルドされます。docs/iot.mdを参照してください。サイズのスペクトルの反対側では、その同じ組み込みコアが@goliapkg/kevyとしてブラウザ上でも走ります——docs/wasm.mdを参照してください。

階層化と TABLE 層(4.0 での新顔、すべて加算的)

4.0 は透過的な階層化(tiering.md)と TABLE.* 層(tables.md)も同梱します。どちらもアップグレードで自動的に有効になることはありません。この節があるのは、足元で何が変わり、何が変わらなかったかを知ってもらうためです。

  • 階層化は opt-in——使わないなら操作はゼロ。 [tiering] セクションが無ければ(そして with_tier_budget* を呼ばなければ)今日の経路がバイト単位で保たれます。その「切っているときのコスト」自体が門で見張られている主張です。有効にしても永続性の契約は変わりません:AOF は唯一の永続的な真実のままで、<data>/tier/ の下の冷たい値ログは起動ごとに使い捨てです(開くたびに削除され、バックアップされません)。
  • INFO# Tiering セクションが増える——階層化が有効なときだけ。 階層化していない 4.0 サーバの INFO 出力は変わらないので、セクションを列挙するパーサは、あなたが自分で有効にするまで何も新しいものを見ません。
  • 新しい動詞、すべて加算的TABLE.DECLARE / TABLE.DROP / TABLE.LIST / TABLE.VERIFYIDX.QUERY / IDX.COUNTWHERE 形(複合の先頭接頭辞による探索)、そしてスカラの句一式——IDX.CREATE 時の VALUES、クエリ時の FILTER / SORT / DISTINCT / FACET / OFFSET——は、以前はテキスト専用でしたが、いまは range/unique の kind でも使えます。既存の動詞で形が変わったものはありません。
  • 新しいクレートが二つワークスペースに加わります:kevy-vlog(冷たい値ログの石)と kevy-sql(エンジンの外にある宣言時の SQL コンパイラ、kevy-cli sql という顔つき)。組み込みには tier という cargo フィーチャが増えます(既定の集合に入っています——上の表を参照)。
  • サイドカーのカタログ版 v5/v6。 インデックスカタログのサイドカーに v5(スカラ kind が保存する VALUES)と v6(複合 ORDERPATH インデックス)が加わり、新たに table-catalog.meta サイドカーができました。それより古いサイドカー版もすべて読み込めます——最初のインデックス版が残した v1 ファイルを含めて。書き手が出すのはそのデータを表現できる最も古いヘッダです:新しい能力を一つも使っていないカタログは、これまでの版をバイト単位でそのまま書き続けるので、より前の 4.0 系のバイナリからも読めるままです。版が前に進むのは、あなたが実際に新しいものを宣言したときだけです。

4.0 → 3.18のダウングレード

バイナリを戻すだけです。スナップショットとAOFの形式は共有されています。唯一の縁は、新しい通知フラグ(x/e/n)を使っているconfigファイルです。3.18でもパースは通りますが、そこでイベントが発火することはありません。


2.x → 3.x

kevy 3.xは2.xのスーパーセットです。2.xのワークロードはすべてそのまま動き、アップグレードはサーバーならバイナリの差し替え、組み込みユーザーなら依存のバージョン上げです。この章は、何が自動で引き継がれ、何が名前や数字を変え、そしてどの方向にだけ注意が要るのか(2.xへのダウングレード)を明示します。

TL;DR —— バージョンの一覧

コンポーネント2.x時代3.x(最終:3.18.x)やること
kevy(サーバー)2.0.x3.18.xバイナリを差し替え、同じデータディレクトリで再起動する
kevy-embedded1.x(1.4〜1.16)3.x依存を上げる —— ワークスペース全体が1つのバージョンに統一されたv3.0.0で、1.xのラインは終わりました
kevy-client1.12.x1.13〜1.14上げるだけ。APIは不変
kevy-client-async1.0.x1.1.x上げるだけ。APIは不変
kevy-cli未公開3.xcargo install kevy-cli —— 移行ツールチェーン一式を運ぶようになりました
インフラcrate(kevy-storekevy-rt、…)2.0.x3.xワークスペースのバージョンに追従する

kevy-embeddedの1.xから3.xへの跳躍は、バージョンラインの統一であって、APIの書き直しではありません。1.16の面は3.xに含まれています。Cargo.tomlkevy-embedded = "1"と書いてあるなら"3"に変えて再ビルドしてください——あるいは、上の章とともに一気に"4"へ進んでください。

自動で互換なもの

ワイヤプロトコル。 RESPは変わっていません。3.xも、CIでvalkey 9.1に対してバイト単位の応答チェックを受け続けています(98コマンド)。既存のRedisクライアント、スクリプト、redis-cliのセッションは以前どおり動きます。

スナップショット。 3.xのローダは、2.xのスナップショット形式をすべて読みます(KEVYSNAPのバージョン2〜5:相対TTLのv2ファイル、絶対TTLのv3、ストリームグループのv4、フィードカーソルのv5)。3.xのサーバーを2.xのデータディレクトリに向ければ、ロードされます。

AOF。 AOFはverbのログであり、3.xのverb集合は2.xのスーパーセットです——リプレイはそのまま動きます。appendfsyncのセマンティクスも変わりません。

Config。 2.xのconfigキーはすべて受け入れられます。新しいセクション([replication] single_source--accept-shards、…)は追加的であり、デフォルトは2.xの振る舞いを再現します。

アップグレードの手順

サーバーのデプロイ

  1. 稼働中の2.xサーバーでスナップショットを取り(SAVEまたは通常のバックアップ)、そのコピーを保管してください——理由は下の「ダウングレード」を参照。
  2. 2.xを止め、同じフラグとデータディレクトリで3.xのバイナリを起動します。
  3. 検証:DBSIZEが一致すること。暗号強度の保証が欲しければ、前後でkevy-cli digest -p <port> <prefix>を走らせてください——ダイジェストが等しければ、キー空間は同一です。

レプリカのペアをローリングで上げる場合:先にレプリカをアップグレードし、再同期させ、トラフィックをそちらへフェイルオーバーしてから、元プライマリをアップグレードします。(2.xに管理されたフェイルオーバーはないので、2.xからだとこれは通常の手動の入れ替えになります。3.15以降に乗れば、そのフェイルオーバーの手順自体が1つのverbになります——FAILOVER host portdocs/availability.mdを参照。)

組み込みアプリケーション

  1. Cargo.tomlkevy-embedded = "3"
  2. リビルドします。1.16のAPIはそのまま存在します。新しい能力の面(index/view/text/vector/feed/replication)は、追加のメソッドとConfigのオプションです。
  3. トレイトについて1点。独自のimpl kevy_rt::Commandsを書いていて、かつResolvedCmdをリテラルで構築している場合に限りますが、v2のアークの途中で2つのフィールドが増えました(block_hintwake_idx)。デフォルトのresolve()はそれらを埋めます。リテラルのコンストラクタには、2つのフィールドを足してください。
  4. 組み込み1.xのアプリが書いたオンディスクのデータは、そのままロードされます(サーバーと同じスナップショット形式です)。

クライアント

kevy-client 1.13+ / kevy-client-async 1.1はドロップインです。マイナーの上げは、内部のcrateを3.xのワークスペースに固定し直しただけです。汎用のRedisクライアントライブラリは、どちらにせよ影響を受けません。

3.xで加わるもの(アップグレードする理由)

hydration付きの宣言型インデックス(IDX.*)、名前付きビュー(VIEW.*)、書き込み時の集約(GROUP BY / 分散top-K)、辞書不要のCJK全文検索とBM25、HNSWによるベクトルKNN(さらにBM25+KNNのハイブリッド融合)、recovery-point契約を持つCDCフィード(FEED.*)、組み込みをプライマリにするレプリケーション、機械可読な契約(COMMAND DOCS、生成されるリファレンス、kevy-mcp MCPサーバー)、可用性のアーク(レプリケーションのラグの真実、FAILOVER、クォーラムのクラッシュ選挙、WAIT / REPL.TOKEN / REPL.WAITの整合性ラダー——docs/availability.md)、そして移行ツールチェーン(kevy-cli import/export/--verify/diff/inspect/digest)です。docs/designing-on-kevy.mddocs/cookbook.mdから始めてください。性能の領収書はbench/PERF-LEDGER.mdにあります。

これらのどれも、暗黙に有効化されることはありません。2.xのワークロードを載せた3.xサーバーは空のカタログを持ち、空のカタログに対するインデックスフックはperfgateのラチェットに載っています(2.x比でリグレッションなし)。

ダウングレード(唯一、注意が要る方向)

3.xのサーバーはスナップショット形式v4を書きます。CDCフィードのカーソルが存在すればv5です。2.xのバイナリはv4までしか読めません。

  • フィードを一度も有効にしていないなら、3.xのスナップショットは2.xでロードされます。
  • フィードが有効だった(v5)なら、2.xはそのファイルを拒否します。ダウングレードの道筋:3.xでkevy-cli export → まっさらな2.xへkevy-cli import。あるいは、手順1で取ったアップグレード前のバックアップを戻し、その間の差分を受け入れてください。

3.xで導入されたverb(IDX.*VIEW.*FEED.*、…)は、当然ながら2.xのバイナリではリプレイされません——それらを使っていたなら、正しいダウングレードはAOFのリプレイではなく、export/importの道です。

バージョン履歴、各1行

  • 3.0.0 —— サービングエンジンの宣言(インデックス、ビュー、FTS、ANN、CDC、オンランプ。ゲートされた11本の列車)。
  • 3.8.0 —— 性能のアーク(valkey 9.1と、redis-stack 7.4.7のRediSearchに対する実測。素の面で1.6〜3.3倍、ANNは再現率1.000で1.64倍の先行、FTSの単一の一般的な語で93倍。組み込みをプライマリにするレプリケーション)。3.0.0と3.8.0のあいだにリリースは切られていません。3.8.0はv3.1〜v3.8の列車を含みます。
  • 3.17.0 —— 可用性のリリース。AIネイティブなサービングの面(機械可読なverb契約、生成されるドキュメント、kevy-mcp、ハイブリッド検索)と、可用性のアーク(レプリケーションのハートビート/ACKの真実、FAILOVER + クォーラムのクラッシュ選挙、整合性ラダー、CIの契約ゲート)。v3.9〜v3.17の列車を含みます。あいだにリリースは切られていません。
  • 3.17.1〜3.17.4 —— メンテナンス。luna-core Luaランタイムのバージョン上げ、ドキュメント/移行の波、初期採用者のフィードバック(kevy-cli --embed)、そしてドキュメント/i18nの磨き上げの波。
  • 3.18.0 —— 構造のリリース。LOCの負債をゼロにし、その上限をCIで強制。さらに6つの石をfuzz(初日の収穫:実バグ4件を修正)。miri/pedantic/missing-docsの一掃、Rust 1.97.0。