# Các Pattern Caching

Caching strategies and patterns for GoodGo microservices including multi-layer cache, Redis caching, cache key naming, TTL strategies, cache invalidation, and cache-aside patterns.
> Các strategies và patterns về caching cho GoodGo microservices bao gồm multi-layer cache, Redis caching, cache key naming, TTL strategies, cache invalidation, và cache-aside patterns.

## Tổng Quan

Caching is a critical performance optimization technique that stores frequently accessed data in fast-access storage. This guide covers multi-layer caching strategies, cache key naming conventions, TTL (Time To Live) strategies, cache invalidation patterns, and best practices for implementing effective caching in GoodGo microservices.

Caching là kỹ thuật tối ưu hiệu suất quan trọng lưu trữ dữ liệu thường xuyên truy cập trong storage có tốc độ truy cập nhanh. Hướng dẫn này bao gồm các strategies multi-layer caching, conventions đặt tên cache keys, TTL strategies, patterns cache invalidation, và best practices để implement caching hiệu quả trong GoodGo microservices.

## Khi Nào Sử Dụng

Use caching patterns when:
- Implementing caching for frequently accessed data
- Optimizing database queries with caching
- Designing cache key naming conventions
- Setting TTL (Time To Live) strategies
- Implementing cache invalidation patterns
- Using multi-layer cache (L1: Memory, L2: Redis)
- Handling cache failures gracefully
- Improving application performance

Sử dụng caching patterns khi:
- Implement caching cho dữ liệu thường xuyên truy cập
- Optimize database queries với caching
- Thiết kế cache key naming conventions
- Thiết lập TTL strategies
- Implement cache invalidation patterns
- Sử dụng multi-layer cache (L1: Memory, L2: Redis)
- Xử lý cache failures một cách graceful
- Cải thiện hiệu suất ứng dụng

## Khái Niệm Chính

### Chiến Lược Cache Đa Tầng

The platform uses a two-layer cache architecture to balance speed and capacity.

Nền tảng sử dụng kiến trúc cache hai tầng để cân bằng tốc độ và dung lượng.

```mermaid
graph TB
    subgraph Application["Application Layer"]
        App[Application Code]
    end
    
    subgraph L1Layer["L1 Cache - Memory (NodeCache)"]
        L1[In-Memory Cache]
        L1Props["• Speed: < 1ms<br/>• Capacity: 10k keys<br/>• TTL: 60s-5min<br/>• Scope: Per-instance"]
    end
    
    subgraph L2Layer["L2 Cache - Redis (Distributed)"]
        L2[Redis Cache]
        L2Props["• Speed: < 5ms<br/>• Capacity: Large<br/>• TTL: Configurable<br/>• Scope: Shared"]
    end
    
    subgraph DataLayer["Data Source"]
        DB[(Database)]
        API[External API]
    end
    
    App -->|Check First| L1
    L1 -->|Miss| L2
    L2 -->|Miss| DB
    L2 -->|Miss| API
    DB -->|Store| L2
    API -->|Store| L2
    L2 -->|Warm| L1
    
    L1 -.-> L1Props
    L2 -.-> L2Props
    
    style L1 fill:#e1f5ff
    style L2 fill:#fff4e1
    style DB fill:#ffe1e1
    style API fill:#ffe1e1
```

**Đặc Điểm Các Tầng / Layer Characteristics:**

**Cache Bộ Nhớ / L1 Cache (Memory)**:
- **Storage**: NodeCache in-memory cache
- **Tốc Độ / Speed**: Very fast (< 1ms access time)
- **Dung Lượng / Capacity**: Limited (10k keys default)
- **TTL**: Short (60 seconds default, max 5 minutes)
- **Phạm Vi / Scope**: Per-instance (not shared across instances)
- **Trường Hợp Sử Dụng / Use Case**: Ultra-fast access for hot data

**Cache Redis / L2 Cache (Redis)**:
- **Storage**: Distributed Redis cache
- **Tốc Độ / Speed**: Fast (< 5ms access time)
- **Dung Lượng / Capacity**: Large
- **TTL**: Longer (configurable)
- **Phạm Vi / Scope**: Shared across all service instances
- **Trường Hợp Sử Dụng / Use Case**: Distributed caching, larger datasets

### Luồng Cache

The cache lookup follows this flow: Check L1 first, if miss check L2, if miss fetch from source and populate both layers.

Luồng lookup cache theo trình tự: Kiểm tra L1 trước, nếu miss thì kiểm tra L2, nếu miss thì fetch từ nguồn và populate cả hai tầng.

```mermaid
flowchart TD
    Start([Request Data]) --> CheckL1{Check L1 Cache<br/>Memory}
    CheckL1 -->|Hit| ReturnL1[Return Data<br/>from L1]
    CheckL1 -->|Miss| CheckL2{Check L2 Cache<br/>Redis}
    CheckL2 -->|Hit| StoreL1[Store in L1<br/>Warm Cache]
    StoreL1 --> ReturnL2[Return Data<br/>from L2]
    CheckL2 -->|Miss| FetchSource[Fetch from<br/>Data Source]
    FetchSource --> StoreBoth[Store in L1 & L2]
    StoreBoth --> ReturnSource[Return Data<br/>from Source]
    
    ReturnL1 --> End([End])
    ReturnL2 --> End
    ReturnSource --> End
    
    style CheckL1 fill:#e1f5ff
    style CheckL2 fill:#fff4e1
    style FetchSource fill:#ffe1e1
    style ReturnL1 fill:#e1ffe1
    style ReturnL2 fill:#e1ffe1
    style ReturnSource fill:#e1ffe1
```

**Tham Khảo**: [`services/iam-service/src/core/cache/multi-layer-cache.ts`](../../../services/iam-service/src/core/cache/multi-layer-cache.ts)

## Patterns

### Sử Dụng Cache Service

Use the cache service wrapper for all cache operations.

Sử dụng cache service wrapper cho tất cả các thao tác cache.

```typescript
import { cacheService } from '../core/cache';

// Get/set đơn giản
const cached = await cacheService.get<User>('user:123');
await cacheService.set('user:123', userData, 300); // 5 minutes TTL

// Pattern get or set (cache-aside)
const user = await cacheService.getOrSet(
  'user:123',
  async () => {
    return await userRepository.findById('123');
  },
  300 // TTL in seconds
);
```

**Tham Khảo**: [`services/iam-service/src/core/cache/cache.service.ts`](../../../services/iam-service/src/core/cache/cache.service.ts)

### Quy Ước Đặt Tên Cache Key

Use consistent naming patterns to avoid collisions and enable pattern-based invalidation.

Sử dụng patterns đặt tên nhất quán để tránh collisions và cho phép invalidation dựa trên pattern.

**Các Patterns**:
```typescript
// Pattern: {entity}:{identifier}
'user:123'
'user:email:user@example.com'
'user:123:permissions'
'user:123:roles'

// Pattern: {entity}:{identifier}:{sub-resource}
'session:abc123'
'permission:perm_123'
'role:role_123'
```

**Bộ Tạo Key**:
```typescript
cacheService.keys = {
  user: (userId: string) => `user:${userId}`,
  userPermissions: (userId: string) => `user:${userId}:permissions`,
  userRoles: (userId: string) => `user:${userId}:roles`,
  token: (token: string) => `token:${token}`,
  session: (sessionId: string) => `session:${sessionId}`,
};
```

### Pattern Cache-Aside

The most common caching pattern - check cache first, fetch if miss, store in cache.

Pattern caching phổ biến nhất - kiểm tra cache trước, fetch nếu miss, lưu vào cache.

```typescript
async getUserPermissions(userId: string): Promise<string[]> {
  const cacheKey = cacheService.keys.userPermissions(userId);
  
// Thử cache trước
  const cached = await cacheService.get<string[]>(cacheKey);
  if (cached) {
    return cached;
  }
  
// Cache miss - fetch từ nguồn
  const permissions = await calculatePermissions(userId);
  
// Lưu vào cache
  await cacheService.set(cacheKey, permissions, 300); // 5 min TTL
  
  return permissions;
}
```

**Tham Khảo**: [`services/iam-service/src/modules/rbac/rbac.service.ts`](../../../services/iam-service/src/modules/rbac/rbac.service.ts)

### Pattern Get hoặc Set

Simplified cache-aside pattern that automatically handles cache miss scenarios.

Pattern cache-aside đơn giản hóa tự động xử lý các trường hợp cache miss.

```typescript
const permissions = await cacheService.getOrSet(
  cacheService.keys.userPermissions(userId),
  async () => {
// Function này chỉ chạy khi cache miss
    return await calculatePermissions(userId);
  },
  300 // TTL
);
```

### Chiến Lược TTL

Choose TTL (Time To Live) based on data characteristics and change frequency.

Chọn TTL (Time To Live) dựa trên đặc điểm dữ liệu và tần suất thay đổi.

**Short TTL (60-300s) / TTL Ngắn**: Frequently changing data / Dữ liệu thay đổi thường xuyên
- User permissions (300s)
- Session data (varies)
- Real-time statistics / Thống kê thời gian thực

**Medium TTL (300-1800s) / TTL Trung Bình**: Moderately changing data / Dữ liệu thay đổi vừa phải
- User profiles (600s)
- Organization data (900s)
- Configuration (1800s)

**Long TTL (1800-3600s) / TTL Dài**: Rarely changing data / Dữ liệu hiếm khi thay đổi
- Static configurations (3600s)
- Reference data (7200s)

**No TTL / Không TTL**: Very stable data (use with caution) / Dữ liệu rất ổn định (sử dụng cẩn thận)
- Rarely use - prefer long TTL instead / Hiếm khi sử dụng - nên dùng TTL dài

### Làm Mất Hiệu Lực Cache

Invalidate cache when data changes to prevent serving stale data. The platform supports multiple invalidation strategies.

Làm mất hiệu lực cache khi dữ liệu thay đổi để tránh phục vụ dữ liệu cũ. Nền tảng hỗ trợ nhiều chiến lược invalidation.

```mermaid
flowchart TD
    Start([Data Changed]) --> ChooseStrategy{Choose<br/>Invalidation<br/>Strategy}
    
    ChooseStrategy -->|Single Key| SingleKey[Single Key<br/>Invalidation]
    SingleKey --> DelL1[Delete from L1]
    DelL1 --> DelL2[Delete from L2]
    DelL2 --> Done1([Complete])
    
    ChooseStrategy -->|Pattern Match| PatternMatch[Pattern-Based<br/>Invalidation]
    PatternMatch --> FindKeys[Find Matching Keys<br/>user:123:*]
    FindKeys --> DelManyL1[Delete from L1<br/>All Matching]
    DelManyL1 --> DelManyL2[Delete from L2<br/>All Matching]
    DelManyL2 --> Done2([Complete])
    
    ChooseStrategy -->|Multiple Keys| MultipleKeys[Multiple Keys<br/>Invalidation]
    MultipleKeys --> ListKeys[List Keys to Delete<br/>user:123<br/>user:123:permissions<br/>user:123:roles]
    ListKeys --> BatchDelL1[Batch Delete from L1]
    BatchDelL1 --> BatchDelL2[Batch Delete from L2]
    BatchDelL2 --> Done3([Complete])
    
    style SingleKey fill:#e1f5ff
    style PatternMatch fill:#fff4e1
    style MultipleKeys fill:#ffe1e1
    style Done1 fill:#e1ffe1
    style Done2 fill:#e1ffe1
    style Done3 fill:#e1ffe1
```

**Ví Dụ Triển Khai / Implementation Examples:**

```typescript
// Làm mất hiệu lực key đơn / Single key invalidation
await cacheService.del(cacheService.keys.user(userId));
await cacheService.del(cacheService.keys.userPermissions(userId));

// Làm mất hiệu lực dựa trên pattern / Pattern-based invalidation
await cacheService.invalidatePattern('user:123:*');

// Nhiều keys / Multiple keys
await cacheService.delMany([
  cacheService.keys.user(userId),
  cacheService.keys.userPermissions(userId),
  cacheService.keys.userRoles(userId),
]);
```

### Làm Nóng Cache

Pre-populate cache with frequently accessed data to improve initial performance.

Pre-populate cache với dữ liệu thường xuyên truy cập để cải thiện hiệu suất ban đầu.

```typescript
async warmCache() {
  const activeUsers = await userRepository.findActiveUsers();
  
  for (const user of activeUsers) {
// Pre-cache dữ liệu user
    await cacheService.set(
      cacheService.keys.user(user.id),
      user,
      600
    );
    
// Pre-cache permissions
    const permissions = await calculatePermissions(user.id);
    await cacheService.set(
      cacheService.keys.userPermissions(user.id),
      permissions,
      300
    );
  }
}
```

### Xử Lý Lỗi

Cache failures should not break the application - always fallback to data source.

Cache failures không nên làm hỏng ứng dụng - luôn fallback về data source.

```typescript
async getWithCache(key: string): Promise<Data | null> {
  try {
// Thử cache trước
    const cached = await cacheService.get<Data>(key);
    if (cached) return cached;
  } catch (error) {
// Log nhưng tiếp tục - fallback về nguồn
    logger.warn('Cache get failed, falling back to source', { key, error });
  }
  
// Fallback về data source
  return await fetchFromSource();
}
```

## Thực Hành Tốt Nhất

1. **Cache Keys / Cache Keys**: Sử dụng naming conventions nhất quán
2. **TTL Selection / Chọn TTL**: Chọn TTL dựa trên tần suất thay đổi dữ liệu
3. **Invalidation / Làm Mất Hiệu Lực**: Làm mất hiệu lực cache khi dữ liệu thay đổi
4. **Error Handling / Xử Lý Lỗi**: Không để cache failures làm hỏng ứng dụng
5. **Cache-Aside / Cache-Aside**: Sử dụng cache-aside pattern cho hầu hết các trường hợp
6. **Avoid Over-Caching / Tránh Cache Quá Nhiều**: Không cache dữ liệu thay đổi quá thường xuyên
7. **Monitor Hit Rates / Giám Sát Tỷ Lệ Hit**: Theo dõi cache hit rates để optimize TTL
8. **Warm Cache / Làm Nóng Cache**: Pre-populate cache cho critical data
9. **Use Multi-Layer / Sử Dụng Đa Tầng**: Tận dụng cả L1 và L2 cache
10. **Serialize Properly / Serialize Đúng Cách**: Đảm bảo dữ liệu có thể JSON serialize

## Lỗi Thường Gặp

1. **Cache Key Collisions / Va Chạm Cache Key**: Sử dụng keys chung chung dẫn đến va chạm
2. **Stale Data / Dữ Liệu Cũ**: Không invalidate cache khi dữ liệu thay đổi
3. **Too Short TTL / TTL Quá Ngắn**: Đặt TTL quá ngắn, làm mất lợi ích của cache
4. **Too Long TTL / TTL Quá Dài**: Đặt TTL quá dài, phục vụ dữ liệu cũ
5. **No Error Handling / Không Xử Lý Lỗi**: Để cache errors làm hỏng ứng dụng
6. **Caching Everything / Cache Tất Cả**: Cache dữ liệu không có lợi từ caching
7. **Not Warming Cache / Không Làm Nóng Cache**: Không pre-populate critical cache data
8. **Ignoring Hit Rates / Bỏ Qua Tỷ Lệ Hit**: Không monitor cache performance

## Xử Lý Sự Cố

### Tỷ Lệ Hit Thấp

**Problem / Vấn Đề**: Cache hit rate thấp, cache không hiệu quả

**Solution / Giải Pháp**: 
- Review TTL values - có thể quá ngắn
- Check cache key patterns - đảm bảo sử dụng nhất quán
- Verify cache invalidation không quá aggressive
- Monitor dữ liệu nào đang được cache

### Vấn Đề Dữ Liệu Cũ

**Problem / Vấn Đề**: Phục vụ dữ liệu cũ từ cache

**Solution / Giải Pháp**:
- Review TTL values - có thể quá dài
- Đảm bảo cache invalidation khi dữ liệu cập nhật
- Sử dụng TTL ngắn hơn cho dữ liệu thay đổi thường xuyên
- Implement cache versioning nếu cần

### Vấn Đề Hiệu Suất Cache

**Problem / Vấn Đề**: Cache operations chậm

**Solution / Giải Pháp**:
- Kiểm tra Redis connection và network latency
- Monitor Redis memory usage
- Review cache key patterns để hiệu quả
- Xem xét L1 cache hit rate (nên cao)

## Tài Nguyên

- [Multi-Layer Cache](../../../services/iam-service/src/core/cache/multi-layer-cache.ts) - Multi-layer cache implementation
- [Cache Service](../../../services/iam-service/src/core/cache/cache.service.ts) - Cache service wrapper
- [Cache Usage Example](../../../services/iam-service/src/modules/rbac/rbac.service.ts) - Real-world cache usage example
- [Redis Configuration](../../../services/iam-service/src/config/redis.config.ts) - Redis configuration
