いくつかのスポーツ イベント シリーズの結果データベースであるプロジェクトがあります。ご想像のとおり、ほとんどのコンテンツは多かれ少なかれ同じままです。データベース クエリを保存するために、コンテンツの一部をキャッシュしたいと考えています。
プロジェクトは PHP を使用してビルドされ、カスタム MVC を使用しています。キャッシュ ロジックをどこに追加しますか?
いくつかのスポーツ イベント シリーズの結果データベースであるプロジェクトがあります。ご想像のとおり、ほとんどのコンテンツは多かれ少なかれ同じままです。データベース クエリを保存するために、コンテンツの一部をキャッシュしたいと考えています。
プロジェクトは PHP を使用してビルドされ、カスタム MVC を使用しています。キャッシュ ロジックをどこに追加しますか?
Memcached を使用します。このように、クエリの結果をキャッシュし、DB の前にキャッシュから取得してみます。
編集: データに json_encoding を追加しました... json_encode は、配列の PHP のデフォルトのシリアル化よりもわずかに高速であり、データにアクセスする他のアプリケーションで使用できます。
Memcached はデフォルトで FastLZ 圧縮を使用します。
// The ID of the item you're looking for (from $_GET or whatever)
$id = 1;
// Create a memcached instance
$m = new Memcached();
$m->addServer('localhost', 11211);
// Try retrieving the event from memcached
$data = $m->get('event_' . $id);
if ($data) {
// If you found data in memcached, decode it for use in code
$data = json_decode($data);
} else {
// If you didn't find the data in memcached, try retrieving from the DB
$result = mysqli_query('SELECT * FROM events WHERE id = ' . $id);
// If you found results in the DB...
if ($data = mysqli_fetch_assoc($result)) {
// Save them to memcached for future calls
// Note: here, I'm using the optional param to expire it after 1 day
$m->set('event_' . $id, json_encode($data), 86400);
}
}
// Now you can use your data
var_dump($data);
コードにコメントを追加するように編集
MVC および MVC にインスパイアされた設計パターンでキャッシュを使用できるポイントが 2 つあります。出力とデータの取得です。
これは、UI ロジックの一部としてビューに実装する必要があります (ビューは単なるダム テンプレートではなく、インスタンスである必要があります)。どこかは、ビューが応答でテンプレートを結合しているのと同じ領域です。この場合のみ、一部の「テンプレート」は実際には完全に変数なしになります。
このようにして、MVC のコンテキストで HTML のフラグメントをキャッシュできますが、これは特定のユースケースには当てはまりません。データ ソースとのやり取りに時間がかかりすぎる場合に適しています。ストレージが実際に REST API であるときのように。
この機能を有効にするには、モデル レイヤー内で実行する必要があります。正確には、サービス (ドメインとストレージ ロジック間の相互作用を主に含むクラス/インスタンス) 内です。
アプリケーション、ドメイン、およびストレージ ロジックを分離する、完全に実装されたモデル レイヤーがある場合、キャッシュの実装は単に別の形式のストレージとして見えます。
$user = new User;
$cache = new UserCacheMapper;
$user->setId( 42 );
if ( ! $cache->fetch( $user ) )
{
$storage = new UserSQLMapper( $pdo );
$storage->fetch( $user );
$cache->store( $user );
}
// the $user object has been initialized
オブジェクトの初期化は、実際にはサービス内のファクトリによって実行される必要がありますが、これは単純化された例です
このようにして、キャッシュせずにアプリケーションを作成し、後でサービス(アプリケーション ロジックを担当する) を変更して追加することができます。ドメイン オブジェクト(ドメイン ロジック) もデータ マッパー(ストレージ ロジック) も変更する必要はありません。
memcachedを使用してキャッシュソリューションを構築するのは非常に簡単なので、memcachedを使用しましたhttp://memcached.org/
私は通常、キャッシングロジックをコントローラーに配置しますが、モデルの使用状況がキャッシング戦略に影響を与える可能性があるため、通常はモデルの方が適切な場所である可能性があります。
それをモデルに入れると、キャッシング戦略が残りのデータアクセス機能と一致するようになります。これは、モデルを交換でき、キャッシングコードがそれに伴って移動することを意味します。これが失敗する可能性があるのは、モデルに入れることができない複雑な無効化がある場合です。
「コンピュータサイエンスには、キャッシュの無効化と名前の付け方という2つの難しいことがあります」Phil Karlton
独自の MVC パターン フレームワークを使用しているとのことなので、具体的な推奨事項を提示するのは困難です。
キャッシュできる場所がいくつかあります。
HTTP を適切に使用する場合 (冪等性、etags、キャッシュ制御ヘッダーなど)、キャッシュ レイヤーをアプリケーションの外部に配置し、 varnishのようなフォワード キャッシュを使用してページ全体をキャッシュすることでメリットが得られる場合があります。ただし、HTTP は間違いやすいため、これは適切な方法ではない可能性があります。たとえば、ユーザー アカウントがあり、ログインしているユーザーに応じて同じ URL が異なるサーバー出力を生成する場合、リソースは Cookie の状態に依存するため、HTTP キャッシュを使用できません。(あなたがすべきことは、ユーザーを URL に入れることです。たとえば、 の/mysite/{userid}/profile
代わりに/mysite/profile
.) より高度な機能を介して varnish を使用できる場合もありますが、それはより困難になります。
あなたは、データベース クエリの結果をキャッシュすることに関心があるだけだと言っているので、それについて説明します。
データベース応答をキャッシュする明確に定義されたクエリがいくつかある場合は、コントローラーにロジックを配置できます。モデルをビューに渡す前に、モデルを明示的にキャッシュします。キャッシュする場所が複数ある場合、このソリューションは乱雑なコードベースを生成します。また、異なるコントローラーで同じデータを取得する場合は、同じモデルを取得するすべてのコントローラー コードもキャッシュを参照し、同じキャッシュ キーを使用することを慎重かつ手動で確認する必要があります。明らかに、キャッシュのオンとオフを切り替えることも難しくなります。
よりクリーンなソリューションは、結果を透過的にキャッシュする方法でモデルをラップすることです。これは、コントローラーやモデルに大幅な変更を加えることなく、キャッシュを宣言的に追加できることを意味します。ただし、これには非常に適切に設計されたモデル API が必要ですが、それを持っていない可能性があります。
オブジェクトは Memcache(d) を使用してキャッシュできます。これは、複数サーバーのセットアップに最も役立ちます。単一のサーバーの場合、キャッシュ機能を提供する APC/Xcache などに物を保存できます。
dataaccess メソッドでデータをキャッシュします。