EngineeringSolution ArchitectSystem Design

Session 01 - High Availability & Disaster Recovery

Tổng quan

High Availability (HA) và Disaster Recovery (DR) là hai trụ cột để đảm bảo hệ thống luôn hoạt động và có khả năng phục hồi khi xảy ra sự cố. Hai khái niệm này thường đi chung nhưng giải quyết vấn đề khác nhau:

Khái niệmMục tiêuPhạm vi
High AvailabilityGiảm thiểu downtime trong vận hành bình thườngComponent-level, region-level
Disaster RecoveryPhục hồi sau sự cố nghiêm trọng (thiên tai, mất data center)Region-level, global-level

RTO và RPO

Recovery Time Objective (RTO) - thời gian tối đa chấp nhận được để khôi phục hệ thống sau sự cố.

Recovery Point Objective (RPO) - lượng dữ liệu tối đa chấp nhận mất (tính theo thời gian).

Cách tính RTO/RPO cho hệ thống thực tế

Ví dụ: E-commerce platform
- Doanh thu trung bình: 500 triệu VND/giờ
- Chi phí mỗi giờ downtime: ~500 triệu + uy tín thương hiệu
- Business yêu cầu: mất tối đa 1 giờ doanh thu

=> RTO = 1 giờ (phải restore trong 1 giờ)
=> RPO = 15 phút (chấp nhận mất data 15 phút gần nhất)
TierRTORPOVí dụChi phí tương đối
Tier 1< 1 phút0Payment gateway$$$$$
Tier 2< 15 phút< 5 phútOrder management$$$$
Tier 3< 1 giờ< 15 phútProduct catalog$$$
Tier 4< 4 giờ< 1 giờReporting, analytics$$

HA Patterns

Active-Active

Cả hai (hoặc nhiều) instance đều xử lý traffic đồng thời. Data được replicate giữa các node.

Ưu điểm: Zero downtime failover, tận dụng tối đa resource, giảm latency theo geo.

Nhược điểm: Phức tạp trong data consistency, chi phí cao gấp đôi, conflict resolution khó.

Active-Passive

Chỉ primary instance xử lý traffic. Secondary instance ở trạng thái standby, chỉ nhận replicated data.

Ưu điểm: Đơn giản hơn, không có conflict, chi phí thấp hơn (secondary có thể dùng SKU nhỏ).

Nhược điểm: Failover mất thời gian (thường 2-10 phút), resource secondary bị lãng phí.

So sánh

Tiêu chíActive-ActiveActive-Passive
Failover timeGần như 02-10 phút
Chi phíCao (2x resource)Thấp hơn (standby SKU nhỏ)
Data consistencyEventual consistencyStrong consistency
ComplexityCaoTrung bình
Phù hợpTier 1, mission-criticalTier 2-3, cost-sensitive

Azure DR Toolkit

Geo-Replication cho SQL Database

bash
# Tạo secondary replica ở region khác
az sql db replica create \
  --resource-group myRG \
  --server primary-server \
  --name myDB \
  --partner-server secondary-server \
  --partner-resource-group myRG-dr

# Failover manual khi cần
az sql failover-group set-primary \
  --resource-group myRG \
  --server secondary-server \
  --name my-failover-group

Traffic Manager

bash
# Tạo Traffic Manager profile với priority routing
az network traffic-manager profile create \
  --resource-group myRG \
  --name my-tm-profile \
  --routing-method Priority \
  --unique-dns-name myapp-tm \
  --monitor-protocol HTTPS \
  --monitor-path "/health" \
  --monitor-port 443

# Thêm primary endpoint (priority 1)
az network traffic-manager endpoint create \
  --resource-group myRG \
  --profile-name my-tm-profile \
  --name primary-endpoint \
  --type azureEndpoints \
  --target-resource-id /subscriptions/.../webapps/myapp-primary \
  --priority 1

# Thêm secondary endpoint (priority 2)
az network traffic-manager endpoint create \
  --resource-group myRG \
  --profile-name my-tm-profile \
  --name secondary-endpoint \
  --type azureEndpoints \
  --target-resource-id /subscriptions/.../webapps/myapp-secondary \
  --priority 2

Azure Paired Regions

Azure paired regions đảm bảo ít nhất một region trong pair được ưu tiên recovery. Một số pair phổ biến:

PrimarySecondary
East Asia (Hong Kong)Southeast Asia (Singapore)
Japan EastJapan West
Australia EastAustralia Southeast

Health Checks và Circuit Breakers

Health Check trong ASP.NET Core

csharp
// Program.cs
builder.Services.AddHealthChecks()
    .AddSqlServer(
        connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
        name: "sql-server",
        tags: new[] { "db", "critical" })
    .AddRedis(
        redisConnectionString: builder.Configuration["Redis:ConnectionString"],
        name: "redis",
        tags: new[] { "cache" })
    .AddUrlGroup(
        new Uri("https://external-api.com/health"),
        name: "external-api",
        tags: new[] { "external" });

app.MapHealthChecks("/health", new HealthCheckOptions
{
    Predicate = _ => true,
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

// Endpoint riêng cho liveness (dùng cho k8s hoặc Traffic Manager)
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = _ => false // Chỉ check app có running không
});

// Endpoint cho readiness (check dependencies)
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("critical")
});

Circuit Breaker với Polly

csharp
// Đăng ký HttpClient với Circuit Breaker
builder.Services.AddHttpClient("ExternalApi", client =>
{
    client.BaseAddress = new Uri("https://external-api.com");
})
.AddTransientHttpErrorPolicy(policy =>
    policy.CircuitBreakerAsync(
        handledEventsAllowedBeforeBreaking: 3,    // Mở circuit sau 3 lỗi liên tiếp
        durationOfBreak: TimeSpan.FromSeconds(30), // Mở circuit 30 giây
        onBreak: (outcome, timespan) =>
        {
            Log.Warning("Circuit opened for {Duration}s due to: {Error}",
                timespan.TotalSeconds, outcome.Exception?.Message);
        },
        onReset: () => Log.Information("Circuit closed, resuming calls"),
        onHalfOpen: () => Log.Information("Circuit half-open, testing...")
    ))
.AddTransientHttpErrorPolicy(policy =>
    policy.WaitAndRetryAsync(new[]
    {
        TimeSpan.FromMilliseconds(200),
        TimeSpan.FromMilliseconds(500),
        TimeSpan.FromSeconds(1)
    }));

Azure Site Recovery Playbook

Checklist triển khai DR

  1. Identify - Phân loại workload theo tier (RTO/RPO)
  2. Design - Chọn pattern (Active-Active / Active-Passive) phù hợp từng tier
  3. Implement - Setup replication, failover group, Traffic Manager
  4. Test - DR drill hàng quý, đo thực tế RTO/RPO
  5. Document - Runbook cho từng scenario, contact list, escalation path
  6. Automate - Infrastructure as Code cho cả primary và DR site

DR Drill Template

DR Drill Report - Q1 2026
──────────────────────────
Scenario: Primary region (East Asia) hoàn toàn unavailable
Target RTO: 15 phút | Actual RTO: 12 phút ✅
Target RPO: 5 phút  | Actual RPO: 3 phút  ✅

Steps Executed:
1. Detect failure via Azure Monitor alert       - 2 phút
2. Confirm và initiate failover                 - 3 phút
3. SQL Failover Group auto-failover             - 4 phút
4. Traffic Manager DNS propagation              - 3 phút
5. Verify health checks pass on secondary       - 2 phút

Issues Found:
- Redis cache cold start gây latency spike 5s đầu tiên
- 2 background jobs cần manual restart

Action Items:
- Implement Redis warm-up script cho DR site
- Automate background job failover

Trade-off Analysis

Quyết địnhLựa chọn ALựa chọn BRecommendation
Replication modeSynchronous (RPO=0)Asynchronous (RPO>0)Async cho cross-region (sync quá chậm)
Failover triggerAutomaticManualAuto cho Tier 1, Manual cho Tier 2+ (tránh false positive)
DR site sizeFull capacityScaled downScaled down + auto-scale rules (tiết kiệm 40-60%)
Data strategyFull replicationSelective replicationSelective - chỉ replicate critical data