第7章: キャッシング

データソースからのアクセス——データベース、リモートサービス、永続ストレージなど——には時間がかかります。ネットワークのラウンドトリップ、ディスク読み取り、計算のすべてがレイテンシーに寄与します。キャッシングサービスは最近またはよくアクセスされるデータをメモリに格納し、同じデータに対する後続のリクエストをより速く処理できるようにします。キャッシングは分散システムのパフォーマンスを向上させコストを削減するための最も効果的な技術の一つです。

キャッシングの背後にある基本的な洞察は局所性の原理です:最近アクセスされたデータはすぐに再びアクセスされる可能性が高い(時間的局所性)、最近アクセスされたデータの近くのデータもアクセスされる可能性が高い(空間的局所性)。適切に設計されたキャッシュはこれらのパターンを利用して高い割合のリクエストを低速のバッキングストアではなく高速のインメモリストレージから提供します。

インターフェース

caching/src/lib.rs キャッシングサービスは4つのプロシージャを提供します。getとsetがコアの読み書きインターフェースを形成します。コンフィグレーションサービスとは異なりset操作はエントリの有効期間を制御するTTL(Time-to-Live)パラメータを受け付けます。delete操作は明示的なキャッシュ無効化を可能にしstats操作は運用メトリックを公開します。

pub const GET_PROCEDURE: ProcedureId = 1;
pub const SET_PROCEDURE: ProcedureId = 2;
pub const DELETE_PROCEDURE: ProcedureId = 3;
pub const STATS_PROCEDURE: ProcedureId = 4;

#[derive(Debug, Serializable, Deserializable)]
pub struct GetArgs {
    pub key: String,
}

#[derive(Debug, Serializable, Deserializable)]
pub struct GetResult {
    pub value: String,
    pub hit: i32,
}

#[derive(Debug, Serializable, Deserializable)]
pub struct SetArgs {
    pub key: String,
    pub value: String,
    pub ttl_secs: i32,
}

#[derive(Debug, Serializable, Deserializable)]
pub struct StatsResult {
    pub hits: i32,
    pub misses: i32,
    pub size: i32,
}

実装

caching/src/main.rs キャッシュサーバーは高速キー検索のためのHashMapとアクセス順序追跡のためのVecDequeを組み合わせたインメモリデータ構造を維持します。各エントリは値と有効期限を格納します。これにより時間ベースの有効期限付きLRU(Least Recently Used)エビクションポリシーが実装されます。

const MAX_CAPACITY: usize = 10000;

struct CacheEntry {
    value: String,
    expires_at: Instant,
}

struct Cache {
    entries: HashMap<String, CacheEntry>,
    lru_order: VecDeque<String>,
    hits: i32,
    misses: i32,
    max_capacity: usize,
}

get操作は値を返す前に有効期限を確認します。エントリが期限切れの場合は削除されミスとして扱われます。ヒットの場合キーはLRUキューの先頭に移動され最近アクセスされたことが記録されます。バックグラウンドタスクが定期的に期限切れエントリをクリーンアップしキャッシュが再アクセスされないかもしれない古いデータで一杯になるのを防ぎます。

設計の議論

LRUエビクションポリシーはキャッシュ容量管理のいくつかの戦略の一つです。LRUはアクセスパターンが時間的局所性を示す場合にうまく機能します。他の戦略にはLFU(Least Frequently Used)やランダムエビクションなどがあります。

TTLベースの有効期限は古いデータの提供に対する安全策を提供します。TTLなしではキャッシュされた値はバッキングストアが更新された後も無期限に存続する可能性があります。TTLの選択はトレードオフを表します:短いTTLは古さを減らしますがバッキングストアへの負荷を増加させ、長いTTLはヒット率を改善しますが古いデータを提供するリスクがあります。

statsプロシージャを通じて公開されるヒット/ミスの追跡は運用において非常に有用です。健全なキャッシュは高いヒット率(90%以上のことが多い)を持つべきです。ヒット率の急激な低下はアクセスパターンの変化、設定エラー、または容量問題を示している可能性があります。これらのメトリックはモニタリングサービスが追跡しアラートできるようなシグナルです。