mcpField
G
golang-samber-hot

golang-samber-hot

github.com/samber開発3.7k38.6k 回インストール5 日前に更新
リポジトリ

golang-samber-hot について

Go 1.22 以降のジェネリックなインメモリキャッシュ samber/hot を扱う Go エンジニア向けスキルです。アクセス特性に応じたアルゴリズム選択や、期限、ローダー、監視の設定を説明します。

主な機能

  1. 019 種類のキャッシュ追い出し方式
  2. 02TTL と期限切れエントリーの掃除
  3. 03singleflight による重複排除付きローダー
  4. 04シャーディングと stale-while-revalidate
  5. 05Prometheus メトリクス

活用シーン

  1. 01アクセス特性に応じた追い出し方式の選択
  2. 02データベース読み取りのキャッシュと並行ロードの集約
  3. 03TTL とジッターによる期限管理
  4. 04ヒット率の監視と容量の調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-hot

インストール後、Claude Code で/golang-samber-hotを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
algorithm-guide.md
api-reference.md
production-patterns.md

詳細

ペルソナ: キャッシュをシステム設計上の判断として扱う Go エンジニアです。実測したアクセスパターンに基づいて削除アルゴリズムを選び、ワーキングセットのデータからキャッシュサイズを決め、有効期限、ローダーの失敗、モニタリングへの対応を常に計画します。

Go でのインメモリキャッシュに samber/hot を使用する

Go 1.22 以降に対応した、ジェネリックで型安全なインメモリキャッシュライブラリです。9 種類の削除アルゴリズム、TTL、singleflight による重複排除を備えたローダーチェーン、シャーディング、stale-while-revalidate、Prometheus メトリクスをサポートします。

公式リソース:

このスキルは網羅的ではありません。詳細については、ライブラリのドキュメントとコード例を参照してください。

  • Go パッケージのドキュメント、シンボル、バージョン、インポーター、既知の脆弱性については、Context7 よりも優先して samber/cc-skills-golang@golang-pkg-go-dev スキル(godig)を参照してください。
  • 独自のコードでこのライブラリの使い方を調べる場合(定義、呼び出し箇所、診断)には、samber/cc-skills-golang@golang-gopls スキル(gopls)を参照してください。
  • pkg.go.dev にインデックスされていないドキュメントについては、Context7 を引き続き代替手段として利用できます。
go get -u github.com/samber/hot

アルゴリズムの選択

アクセスパターンに基づいて選択してください。適切でないアルゴリズムを選ぶと、メモリを無駄にするか、ヒット率が大幅に低下します。

アルゴリズム定数最適な用途避けるべきケース
W-TinyLFUhot.WTinyLFU汎用、混合ワークロード(デフォルト)デバッグのしやすさを優先する場合
LRUhot.LRU新しさが重要(セッション、最近のクエリ)頻度も重要な場合(スキャンによる汚染で頻繁に使われる項目が削除されます)
LFUhot.LFU頻度が重要(人気の商品、DNS)アクセスパターンが変化する場合(古くなった人気項目が削除されません)
TinyLFUhot.TinyLFU頻度の偏りがある読み取り中心のワークロード書き込み中心の場合(登録フィルターのオーバーヘッドがあります)
S3FIFOhot.S3FIFO高スループット、スキャンに強い小規模なキャッシュ(1,000 項目未満)
ARChot.ARCパターンが不明な場合の自動調整メモリに制約がある場合(追跡に 2 倍のオーバーヘッドがあります)
TwoQueuehot.TwoQueueホット/コールドに分かれた混合ワークロードチューニングの複雑さが許容できない場合
SIEVEhot.SIEVEシンプルでスキャンに強い LRU の代替アクセスパターンに大きな偏りがある場合
FIFOhot.FIFOシンプルで予測可能な削除順序ヒット率が重要な場合(頻度や新しさを考慮しません)

選択の近道: hot.WTinyLFU から始めてください。プロファイリングの結果、ミス率が SLO に対して高すぎると判明した場合にのみ切り替えます。

アルゴリズムの詳しい比較、ベンチマーク、判断ツリーについては、アルゴリズムガイドを参照してください。

基本的な使い方

TTL 付きの基本的なキャッシュ
import "github.com/samber/hot"

cache := hot.NewHotCache[string, *User](hot.WTinyLFU, 10_000).
    WithTTL(5 * time.Minute).
    WithJanitor().
    Build()
defer cache.StopJanitor()

cache.Set("user:123", user)
cache.SetWithTTL("session:abc", session, 30*time.Minute)

value, found, err := cache.Get("user:123")
ローダーパターン(リードスルー)

ローダーは、見つからないキーを singleflight による重複排除付きで自動的に取得します。同じキーが見つからない場合、並行する Get() 呼び出しは 1 回のローダー呼び出しを共有します。

cache := hot.NewHotCache[int, *User](hot.WTinyLFU, 10_000).
    WithTTL(5 * time.Minute).
    WithLoaders(func(ids []int) (map[int]*User, error) {
        return db.GetUsersByIDs(ctx, ids) // batch query
    }).
    WithJanitor().
    Build()
defer cache.StopJanitor()

user, found, err := cache.Get(123) // triggers loader on miss

容量のサイジング

キャッシュ容量を設定する前に、メモリ予算に収まる項目数を見積もります。

  1. 項目 1 つあたりのサイズを見積もります — 構造体のサイズを見積もり、ヒープに割り当てられるフィールド(スライス、マップ、文字列)のサイズを加算します。キーのサイズも含めます。エントリーあたり約 100 バイトを目安とすると、内部管理(ポインター、有効期限のタイムスタンプ、アルゴリズムのメタデータ)に必要なオーバーヘッドをおおよそカバーできます。
  2. 開発者に確認します — 本番環境で、このキャッシュに割り当てるメモリ量を確認します(例:256 MB、1 GB)。これはサービス全体のメモリ量や、プロセス内でほかに何がメモリを共有しているかによって異なります。
  3. 容量を計算します — capacity = memoryBudget / estimatedItemSize。余裕を残せるよう、切り捨ててください。
Example: *User struct ~500 bytes + string key ~50 bytes + overhead ~100 bytes = ~650 bytes/entry
         256 MB budget → 256_000_000 / 650 ≈ 393,000 items

項目のサイズが不明な場合は、N 個の項目を割り当てて runtime.ReadMemStats を確認するユニットテストで測定するよう、開発者に依頼してください。測定せずに容量を推測すると、OOM やメモリの無駄につながります。

よくある間違い

  1. WithJanitor() を忘れる — これを指定しないと、期限切れのエントリーはアルゴリズムによって追い出されるまでメモリに残ります。ビルダーで必ず .WithJanitor() をチェーンし、defer cache.StopJanitor() を指定してください。
  2. missing cache の設定なしで SetMissing() を呼び出す — 実行時にパニックが発生します。まずビルダーで WithMissingCache(algorithm, capacity) または WithMissingSharedCache() を有効にしてください。
  3. WithoutLocking() と WithJanitor() の併用 — 相互に排他的で、パニックが発生します。WithoutLocking() は、バックグラウンドクリーンアップを行わず、単一ゴルーチンからアクセスする場合にのみ安全です。
  4. キャッシュが大きすぎる — すべてを保持するキャッシュは、オーバーヘッドのあるマップにすぎません。ワーキングセットに合わせてサイズを設定してください(通常は全データの10~20%です)。ヒット率を監視して妥当性を確認してください。
  5. ローダーのエラーを無視する — ローダーでエラーが発生すると、Get() は (zero, false, err) を返します。found だけでなく、必ず err も確認してください。

ベストプラクティス

  1. 必ず TTL を設定してください — 有効期限のないキャッシュは更新の合図がないため、古いデータを無期限に提供します
  2. WithJitter(lambda, upperBound) を使用して有効期限を分散してください — ジッターがないと、同時に作成されたアイテムが同時に期限切れになり、ローダーにサンダリングハードが発生します
  3. WithPrometheusMetrics(cacheName) で監視してください — ヒット率が80%を下回る場合、通常はキャッシュのサイズが不足しているか、ワークロードに適したアルゴリズムではありません
  4. 可変値には WithCopyOnRead(fn) / WithCopyOnWrite(fn) を使用してください — コピーがないと、呼び出し元がキャッシュされたオブジェクトを変更し、共有状態を破損させます

高度なパターン(再検証、シャーディング、missing cache、監視の設定)については、本番環境向けパターンを参照してください。

API の全容については、API リファレンスを参照してください。

samber/hot でバグや予期しない動作に遭遇した場合は、https://github.com/samber/hot/issues で issue を作成してください。

相互参照

  • → 一般的なキャッシュ戦略や、インメモリーキャッシュ、Redis、CDN の使い分けについては、samber/cc-skills-golang@golang-performance スキルを参照してください
  • → Prometheus メトリクスの統合と監視については、samber/cc-skills-golang@golang-observability スキルを参照してください
  • → キャッシュローダーと組み合わせるデータベースクエリのパターンについては、samber/cc-skills-golang@golang-database スキルを参照してください
  • → CLI から Prometheus のキャッシュメトリクスをクエリする方法については、samber/cc-skills@promql-cli スキルを参照してください

コメント