なぜキャッシングが重要なのか
⚡ なぜキャッシングが重要なのか
Section titled “⚡ なぜキャッシングが重要なのか”キャッシングは、アプリケーションのパフォーマンスを向上させる重要な技術です。適切なキャッシングにより、レスポンスタイムを短縮し、サーバーリソースを効率的に使用できます。
🎯 キャッシングの重要性
Section titled “🎯 キャッシングの重要性”❌ キャッシングなしのアプリケーションの問題
Section titled “❌ キャッシングなしのアプリケーションの問題”❌ 問題のある実装:
// キャッシングなし: 毎回データベースにアクセスasync function getUser(userId: string) { // 毎回データベースクエリが実行される const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]); return user;}
// 問題点:// - データベースへの負荷が高い// - レスポンスタイムが遅い// - スケーラビリティが低い⚠️ 影響:
- 📈
データベースの負荷増加 - ⏱️
レスポンスタイムの増加 - 📉
スケーラビリティの低下 - 💸
コストの増加
✅ キャッシングによる解決
Section titled “✅ キャッシングによる解決”✅ 改善された実装:
// キャッシングあり: キャッシュから取得async function getUser(userId: string) { // キャッシュから取得を試みる const cached = await cache.get(`user:${userId}`); if (cached) { return cached; }
// キャッシュにない場合はデータベースから取得 const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
// キャッシュに保存 await cache.set(`user:${userId}`, user, 3600); // 1時間
return user;}
// メリット:// - データベースへの負荷が軽減される// - レスポンスタイムが短縮される// - スケーラビリティが向上するキャッシングの種類
Section titled “キャッシングの種類”1. アプリケーションレベルキャッシング
Section titled “1. アプリケーションレベルキャッシング”定義: アプリケーション内でデータをキャッシュします。
使用例:
// メモリキャッシュconst cache = new Map<string, any>();
function getUser(userId: string) { if (cache.has(userId)) { return cache.get(userId); }
const user = fetchUser(userId); cache.set(userId, user); return user;}2. データベースレベルキャッシング
Section titled “2. データベースレベルキャッシング”定義: データベースのクエリ結果をキャッシュします。
使用例:
-- クエリキャッシュ(MySQL)SET GLOBAL query_cache_size = 1000000;SET GLOBAL query_cache_type = ON;3. CDNキャッシング
Section titled “3. CDNキャッシング”定義: 静的コンテンツをCDNでキャッシュします。
使用例:
// CloudFrontなどのCDNで静的コンテンツをキャッシュ// 画像、CSS、JavaScriptファイルなどキャッシング戦略
Section titled “キャッシング戦略”1. Cache-Aside(Lazy Loading)
Section titled “1. Cache-Aside(Lazy Loading)”定義: アプリケーションがキャッシュを管理します。
フロー:
1. キャッシュからデータを取得を試みる2. キャッシュにない場合はデータベースから取得3. データをキャッシュに保存実装例:
async function getUser(userId: string) { // キャッシュから取得 let user = await cache.get(`user:${userId}`);
if (!user) { // データベースから取得 user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
// キャッシュに保存 await cache.set(`user:${userId}`, user, 3600); }
return user;}2. Write-Through
Section titled “2. Write-Through”定義: データの書き込み時に、キャッシュとデータベースの両方に書き込みます。
フロー:
1. データベースに書き込み2. キャッシュにも書き込み実装例:
async function updateUser(userId: string, data: UserData) { // データベースに書き込み const user = await db.query( 'UPDATE users SET ? WHERE id = ?', [data, userId] );
// キャッシュにも書き込み await cache.set(`user:${userId}`, user, 3600);
return user;}3. Write-Behind(Write-Back)
Section titled “3. Write-Behind(Write-Back)”定義: データの書き込みをキャッシュにのみ行い、後でデータベースに書き込みます。
フロー:
1. キャッシュに書き込み2. 非同期でデータベースに書き込み実装例:
async function updateUser(userId: string, data: UserData) { // キャッシュに書き込み await cache.set(`user:${userId}`, data, 3600);
// 非同期でデータベースに書き込み setImmediate(async () => { await db.query('UPDATE users SET ? WHERE id = ?', [data, userId]); });
return data;}キャッシュ無効化
Section titled “キャッシュ無効化”TTL(Time To Live)ベース
Section titled “TTL(Time To Live)ベース”// TTLを設定して自動的に無効化await cache.set(`user:${userId}`, user, 3600); // 1時間明示的な無効化
Section titled “明示的な無効化”// データ更新時にキャッシュを無効化async function updateUser(userId: string, data: UserData) { await db.query('UPDATE users SET ? WHERE id = ?', [data, userId]);
// キャッシュを無効化 await cache.delete(`user:${userId}`);}キャッシングが重要な理由:
- パフォーマンス: レスポンスタイムを短縮できる
- スケーラビリティ: サーバーリソースを効率的に使用できる
- コスト: データベースへの負荷を軽減できる
- ユーザー体験: ユーザー体験を向上させられる
適切なキャッシングにより、アプリケーションのパフォーマンスを大幅に改善できます。