Memcached のキャッシュ戦略
以下のトピックでは、Memcached キャッシュを設定および維持するための戦略について説明します。
キャッシュするデータとデータへのアクセスパターンに基づいて、キャッシュを入力し維持するために実装する戦略とは何か。たとえば、ゲームサイトやトレンドのニュースのランキングトップ 10 で同じ同じ戦略は使用したくないでしょう。このセクションの後半では、一般的なキャッシュのメンテナンス戦略、利点および欠点について説明します。
遅延読み込み
その名前が示すようため、[遅延読み込み] は、必要なときにのみキャッシュにデータを読み込むキャッシュ戦略です。これは、以下で説明するように動作します。
Amazon ElastiCacheは、インメモリ key-value ストアで、アプリケーションとアプリケーションがアクセスするデータストア (データベース) 間にあります。アプリケーションがデータをリクエストする場合は、常に ElastiCache キャッシュに最初にリクエストを行います。データがキャッシュにあり最新である場合、ElastiCache はアプリケーションにデータを返します。データがキャッシュにない場合、または期限が切れている場合は、アプリケーションはデータストアからのデータをリクエストします。その後、データストアはアプリケーションにデータを返します。次に、アプリケーションは、ストアから受信したデータをキャッシュに書き込みます。このようにして、次回リクエストされたときに、より迅速に取得できます。
[キャッシュヒット] は、データがキャッシュにあり、期限切れでない場合に発生します。
アプリケーションは、キャッシュに対してデータをリクエストします。
キャッシュはアプリケーションにデータを返します。
[キャッシュミス] は、データがキャッシュにないか、期限切れの場合に発生します。
アプリケーションは、キャッシュに対してデータをリクエストします。
キャッシュにはリクエストされたデータがないため、
null
を返します。アプリケーションはデータベースに対してデータをリクエストし、取得します。
アプリケーションは、新しいデータでキャッシュを更新します。
遅延読み込みの利点と欠点
遅延読み込みの利点は次のとおりです。
-
リクエストされたデータのみをキャッシュします。
ほとんどのデータがリクエストされないため、遅延読み込みではデータでキャッシュがいっぱいになることを回避できます。
-
ノード障害は、アプリケーションにとって致命的ではありません。
ノードで障害が発生して新しい空のノードに置き換えられた場合、アプリケーションはレイテンシーが長くなっても機能し続けます。新規ノードへのリクエストが行われると、それぞれのキャッシュミスにより、データベースのクエリが行われます。同時に、後続のリクエストがキャッシュからデータを取得できるように、データコピーがキャッシュに追加されます。
遅延読み込みの欠点は次のとおりです。
遅延読み込み擬似コードの例
次のコードは、遅延読み込みロジックの擬似コードの例です。
// *****************************************
// function that returns a customer's record.
// Attempts to retrieve the record from the cache.
// If it is retrieved, the record is returned to the application.
// If the record is not retrieved from the cache, it is
// retrieved from the database,
// added to the cache, and
// returned to the application
// *****************************************
get_customer(customer_id)
customer_record = cache.get(customer_id)
if (customer_record == null)
customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id)
cache.set(customer_id, customer_record)
return customer_record
この例では、データを取得するアプリケーションコードは次のとおりです。
customer_record = get_customer(12345)
書き込みスルー
書き込みスルー戦略では、データがデータベースに書き込まれると常にデータを追加するか、キャッシュのデータを更新します。
書き込みスルーの利点と欠点
書き込みスルーの利点は次のとおりです。
-
キャッシュのデータが古くなりません。
キャッシュにデータベースにデータが書き込まれるたびにキャッシュのデータが更新されるため、キャッシュのデータが常に最新の状態になります。
-
書き込みペナルティ対読み取りペナルティ。
1 回の書き込みで 2 回のトリップ:
キャッシュへの書き込み
データベースへの書き込み
レイテンシーをプロセスに追加します。つまり、エンドユーザーは一般的に、データの取得時よりもデータの更新時のレイテンシーに対して寛容です。更新は作業量が大きく時間がかかるのが常です。
書き込みスルーの欠点は次のとおりです。
-
欠落データ。
ノード障害またはスケールアウトにより、新規ノードをスピンアップすると、データが欠落しています。このデータは、データベースで追加または更新されるまで失われ続けます。これを最小限に抑えるには、[遅延読み込み] を書き込みスルーで指定します。
-
キャッシュの変動。
ほとんどのデータは読み込まれないため、これはリソース浪費です。[有効期限 (TTL) の値を追加する] を使用すると、無駄なスペースを最小限に抑えることができます。
書き込みスルー擬似コードの例
以下は、書き込みスルーロジックの擬似コードの例です。
// *****************************************
// function that saves a customer's record.
// *****************************************
save_customer(customer_id, values)
customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values)
cache.set(customer_id, customer_record)
return success
この例では、データを取得するアプリケーションコードは次のとおりです。
save_customer(12345,{"address":"123 Main"})
TTL の追加
遅延読み取りはデータが古くなる可能性がありますが、空ノードによる障害は発生しません。書き込みスルーでは常に新しいデータとなりますが、空ノードの障害が発生して、過剰なデータがキャッシュに入力される可能性があります。それぞれの書き込みに有効期限 (TTL) の値を追加することで、それぞれの戦略のメリットが得られます。同時に、過剰なデータでキャッシュがいっぱいになる事態が避けられます。
[有効期限 (TTL)] は、キーの有効期限までの秒数を指定する整数値です。Valkey または Redis OSS では、この値の秒またはミリ秒を指定できます。Memcached は、この値を秒単位で指定します。アプリケーションが期限切れのキーを読み込もうとすると、キーが見つからないものとして処理されます。データベースにキーについてクエリされ、キャッシュが更新されます。このアプローチは、値が古くなっていないことを保証するものではありません。ただし、これはデータが古くなりすぎることを防ぎ、キャッシュの値がデータベースから時々更新されることを必要とします。
詳細については、「Valkey and Redis OSS commandsset
commands
TTL 擬似コードの例
以下は、TTL のある書き込みスルーロジックの擬似コードの例です。
// *****************************************
// function that saves a customer's record.
// The TTL value of 300 means that the record expires
// 300 seconds (5 minutes) after the set command
// and future reads will have to query the database.
// *****************************************
save_customer(customer_id, values)
customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values)
cache.set(customer_id, customer_record, 300
)
return success
以下は、TTL のある遅延読み込みロジックの擬似コードの例です。
// *****************************************
// function that returns a customer's record.
// Attempts to retrieve the record from the cache.
// If it is retrieved, the record is returned to the application.
// If the record is not retrieved from the cache, it is
// retrieved from the database,
// added to the cache, and
// returned to the application.
// The TTL value of 300 means that the record expires
// 300 seconds (5 minutes) after the set command
// and subsequent reads will have to query the database.
// *****************************************
get_customer(customer_id)
customer_record = cache.get(customer_id)
if (customer_record != null)
if (customer_record.TTL < 300)
return customer_record // return the record and exit function
// do this only if the record did not exist in the cache OR
// the TTL was >= 300, i.e., the record in the cache had expired.
customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id)
cache.set(customer_id, customer_record, 300
) // update the cache
return customer_record // return the newly retrieved record and exit function
この例では、データを取得するアプリケーションコードは次のとおりです。
save_customer(12345,{"address":"123 Main"})
customer_record = get_customer(12345)