はじめに
小さな店では、正しい価格を準備済みのプライマリデータベースに保管し、顧客がすでに見た価格を Redis に記憶させています。繰り返しの表示では、その記憶した値を使うべきです。しかし、同じ SKU でも店舗や通貨によって価格が異なり、記憶した価格もいつか期限切れになる必要があります。
キャッシュの完全な識別情報を決め、各格納に有限の有効期間を設定する短い policy.py を作ります。基本的なターミナル操作と Redis の GET/SET の知識が必要です。Python のひな型と変更する各式はここで説明するため、Python コースの受講歴は不要です。プライマリは準備済みの SQLite データベースであり、別のデータベースを実装するタスクではありません。この独立した単元には新しいデータがあり、Terminal だけを使います。
編集するのは /home/labex/project/cache-desk/policy.py だけです。提供されたツール、元テーブル、元のすべての識別情報と価格、無関係なカタログメモを保全します。3 関数内では、説明された source/cache API と通常のポリシー式だけを使い、import、シェル実行、無関係なリソースは含めません。キャッシュ機能の停止、Redis の広範な消去、全体設定の変更はしません。制御された逐次リクエストを検証するもので、本番遅延や強い整合性を保証しません。作者の所要時間の見積もりは読解と通常のミスを含みますが、初心者で計測したものではありません。
顧客が実際に求める価格を区別する
このステップでは、実際のキャッシュヒットを観察し、キーの衝突を見つけ、各価格の完全な識別情報をキーに含めます。
Terminal のシェルプロンプトから始めます。cd は現在のディレクトリを移動し、この絶対パスはどのディレクトリからでも使えます。./desk はそのディレクトリの準備済みプログラムを実行します。以下はそれぞれ別のシェルコマンドであり、対話型 Redis プロンプトへの入力ではありません。
cd /home/labex/project/cache-desk
./desk status
列順は shop / sku / currency / integer cents です。North MUG USD は 1200 セント、South MUG USD は 1500、North MUG EUR は 1100、North FREE USD は 0 です。状態表示は正しい元の価格を読み、キャッシュへの格納はしません。
キャッシュミスは、要求したキーに Redis の値がないこと、キャッシュヒットは値があることです。この準備済みアプリはキャッシュアサイドを使います。まず Redis を読み、ミスの場合だけプライマリを読んで、その結果を記憶します。同じ通常のリクエストを 2 回試します。
./desk view north MUG USD
./desk view north MUG USD
最初は "cents": 1200、"origin": "source"、"primary_selects": 1、2 回目は "origin": "cache"、"primary_selects": 0 が表示されるはずです。この回数はリクエストのネイティブな SQLite SELECT トレースから得られ、推定の高速化率ではありません。JSON 出力は引用符付きのフィールド名を使い、この 3 フィールドが価格、取得元、プライマリ読み取り回数を示します。
別の店舗を要求し、実際の Redis キーを確認します。
./desk view south MUG USD
./desk inspect south MUG USD
./desk policy
不完全なキーは MUG しか使いません。プライマリがまだ 1500 を保持していても、South に North の 1200 を返すことがあります。inspect はキーと実際の値を読み、価格を修復しません。提供された接頭辞 catalog は、このコースのキーを区切ります。すべてのキーは、catalog: のように、提供された接頭辞にコロンを続けて始める必要があります。接尾辞は SKU だけでなく 3 つの識別フィールドすべてを区別します。同等の接尾辞の符号化も受け入れられます。
ひな型は Python です。def は関数を定義し、括弧内の名前は引数です。インデントした本体はその関数に属します。return は結果を返します。identity は、表示順に並ぶ 3 項目のタプルです。identity[0] は店舗、[1] は SKU、[2] は通貨です。インデックスはゼロ始まりです。f"...{name}..." は式を文字列に挿入します。ここでのコロンは普通の区切り文字です。コースの識別子は英数字、ハイフン、アンダースコアだけなので、この区切り文字を含みません。このキー形式は任意のユーザーテキストの汎用符号化ではありません。
read_price 内の = は値を代入します。cache.command("GET", key) は実際の Redis コマンドを送ります。None はキャッシュ値がないことを意味し、if value is not None: は値が存在する場合だけ分岐します。この明示的な検査により、価格ゼロも保たれます。Redis は文字列値を返すため、int(value) で整数のセントに変換します。return cents, "source" のカンマは 2 値の組を返します。source.read(identity) は準備済みのプライマリ SELECT を実行し、未知の識別情報では検索エラーを送出します。代わりの正解価格はありません。
完全なキーを持つファイル全体を保存します。cat > policy.py はファイルを置き換えます。引用符付きヒアドキュメントマーカー 'POLICY' により、シェルは単独行の POLICY までをそのままコピーします。4 個の空白のインデントを保って、ブロック全体をコピーします。繰り返した関数は準備済みの読み取り動作を保ち、このステップではキーの判断だけを変更します。
cat > policy.py <<'POLICY'
def cache_key(prefix, identity):
return f"{prefix}:{identity[0]}:{identity[1]}:{identity[2]}"
def read_price(source, cache, prefix, identity):
key = cache_key(prefix, identity)
value = cache.command("GET", key)
if value is not None:
return int(value), "cache"
cents = source.read(identity)
cache.command("SET", key, cents)
return cents, "source"
def change_price(source, cache, prefix, identity, cents):
source.write(identity, cents)
POLICY
各識別情報を 2 回ずつ表示します。
./desk view north MUG USD
./desk view north MUG USD
./desk view south MUG USD
./desk view south MUG USD
./desk view north MUG EUR
./desk view north MUG EUR
./desk view north FREE USD
./desk view north FREE USD
新しい完全なキーの最初の読み取りは source、2 回目は Redis です。価格は順に 1200、1500、1100、0 です。誤った価格のキャッシュヒットは成功ではありません。古い使い捨ての catalog:MUG キーはもう使われず、広範な削除は不要です。
./deskk と入力すると、シェルはファイルがないと報告します。ls で実際のツールを確認し、正しいつづりで ./desk を再実行します。Python が構文・インデントエラーを報告したら、./desk policy を表示し、行頭の空白を保って完全なファイルのブロックを再度コピーします。VM をリセットしたり、準備済みツールを変えたりしないでください。このステップのチェックは使い捨てのテスト環境で異なる識別情報を試し、実際のプライマリを保全します。特定のキーのつづりを要求するものではありません。
各格納に有効期限を設ける
このステップでは、価格を Redis に格納するときに有限の有効期間を付け、ヒットで期限が延びないようにします。
Terminal の /home/labex/project/cache-desk で続けます。既存の完全なキーを確認します。
./desk inspect north MUG USD
pttl_ms はミリ秒単位の残り有効期間です。-1 は期限なし、-2 はキーがないことを意味します。正の値は減少していきます。期限のない値は、外部で価格が変わっても無期限に残ることがあります。
Redis の SET key value EX seconds は、値と有効期限を 1 コマンドで保存します。この教材の店では 15 秒を選びます。受け入れられる格納時の有効期間は 12~20 秒です。自然な期限切れを観察できる短さであり、本番 TTL の推奨ではありません。期限を設定するのはミス時だけです。ヒットのたびに更新すると、人気の古い価格が無期限に残ることがあります。期限付きキーを通常の SET で上書きすると、明示的に保持を要求しない限り、古い期限は消えます。
同じ完全な識別情報と、期限付き SET を使うファイルで置き換えます。Python の別々の引数 "EX", 15 が Redis に渡ります。15 は整数であり、引用符付きの識別子ではありません。
cat > policy.py <<'POLICY'
def cache_key(prefix, identity):
return f"{prefix}:{identity[0]}:{identity[1]}:{identity[2]}"
def read_price(source, cache, prefix, identity):
key = cache_key(prefix, identity)
value = cache.command("GET", key)
if value is not None:
return int(value), "cache"
cents = source.read(identity)
cache.command("SET", key, cents, "EX", 15)
return cents, "source"
def change_price(source, cache, prefix, identity, cents):
source.write(identity, cents)
POLICY
前のステップで格納した完全な識別情報の値は、まだ期限なしです。コード変更で過去の格納に期限が追加されるわけではありません。forget は、既知の識別情報 1 つの現在のキャッシュキーだけを明示的に削除し、プライマリ価格や他のキーは保ちます。明示的に使い捨てとした練習用 4 エントリーを、個別に削除します。これは学習者の明示的操作であり、広範なフラッシュや読み取り側の隠れた修復ではありません。その後の格納はすべて新しい期限を使います。続いて North の価格を格納し、確認します。
./desk forget north MUG USD
./desk forget south MUG USD
./desk forget north MUG EUR
./desk forget north FREE USD
./desk view north MUG USD
./desk inspect north MUG USD
./desk view north MUG USD
./desk inspect north MUG USD
最初の表示は source/1、期限前なら次は cache/0 です。正の PTTL は 15000 に戻らず減ります。読解に 15 秒以上かかった場合、実際のミスは想定どおりです。ポリシーを変えず、格納と確認のコマンドを手早く繰り返してください。
提供された読み取り専用接続で、Redis 本来の値も読めます。./redis は一般の Redis サービスではなく、このコース専用の Redis に引数を送ります。
./redis GET catalog:north:MUG:USD
./redis TTL catalog:north:MUG:USD
ラッパーは "1200" のような JSON 文字列、ネイティブな整数 TTL、または値の不在を表す null を表示します。欠けた価格を取りに行くことはありません。sleep 16 は、シェルに実際の 16 秒の待機を要求します。時間のシミュレーションや、代わりのキー削除はしません。
sleep 16
./desk inspect north MUG USD
./desk view north MUG USD
./desk view north MUG USD
再格納の前の inspect は value: null と PTTL -2 を表示します。次の view は再び source を読み、その次は Redis にヒットできます。この単元の正しい元価格はすべて不変です。採点は隔離したキーで実際の期限切れを試します。実際のキーは読解中に自然に切れることがあるため、短いカウントダウンに間に合わせることが完了条件ではありません。
まとめ
実際の Redis キーで店舗・SKU・通貨を区別し、価格ゼロを保ち、プライマリの読み取り回数と照合してキャッシュヒットを確認し、各格納に延長されない有効期間を設定しました。ポリシーは再利用可能で、準備済みのプライマリと無関係なカタログデータはそのままです。



