Part 04 · PostgreSQL & Redis · 4.3

9 lab PostgreSQL và Redis

Mỗi lab phải tạo được failure có kiểm soát, thu evidence trước/sau và kết luận bằng invariant hoặc SLO. Screenshot “chạy được” không đủ; lưu command, config, dataset size, timeline và số đo để người khác tái hiện.


An toàn: chỉ chạy kill, disk pressure, failover, destructive SQL và network partition trong môi trường lab cô lập. Không chạy EXPLAIN ANALYZE trên DML production nếu chưa bọc transaction/rollback và hiểu side effect.
LAB 01 · SCHEMA · 60–90 PHÚT

Schema và business invariants

Mục tiêu: thiết kế order/payment schema có primary key, foreign key, UNIQUE, CHECK, idempotency key và money type an toàn.

Thực hiện

  1. Viết ít nhất bốn invariants trước khi viết DDL: amount dương, currency hợp lệ, một idempotency key chỉ tạo một payment, state transition không nhận giá trị ngoài domain.
  2. Tạo tables bằng numeric hoặc integer minor units; đặt constraints trong database và application validation riêng.
  3. Viết migration expand và rollback/forward-fix plan. Nếu down migration làm mất dữ liệu, ghi rõ vì sao không thể rollback tự động.
  4. Insert dữ liệu hợp lệ rồi cố tình vi phạm từng constraint từ hai writers khác nhau.
  5. Chạy concurrent duplicate insert để chứng minh SELECT-then-INSERT không thay unique constraint.
Evidence: DDL/migration, bảng invariant → constraint, SQL lỗi cùng SQLSTATE, concurrent timeline và query chứng minh không có duplicate/orphan.
LAB 02 · CONCURRENCY · 90–120 PHÚT

Isolation, locking và retry

Mục tiêu: quan sát anomalies và lock waits bằng hai connections thay vì chỉ mô tả lý thuyết.

Thực hiện

  1. Dùng hai psql sessions tái hiện hai SELECT thấy kết quả khác ở Read Committed và snapshot ổn định ở Repeatable Read.
  2. Tạo lost update bằng application read-modify-write, sau đó sửa lần lượt bằng atomic conditional update, version column và SELECT ... FOR UPDATE.
  3. Tạo deadlock bằng khóa hai accounts theo thứ tự ngược; lưu error/deadlock log rồi sửa bằng sorted lock order.
  4. Đặt lock_timeoutstatement_timeout khác nhau để thấy failure semantics.
  5. Implement bounded retry toàn transaction với fresh state, jitter và idempotent external effects.
Evidence: transaction timeline T1/T2, pg_stat_activity/pg_locks, deadlock graph, affected-row counts và retry histogram.
LAB 03 · QUERY CLINIC · 120 PHÚT

Index và EXPLAIN

Mục tiêu: cải thiện một query bằng evidence và lượng hóa write/storage cost của index.

Thực hiện

  1. Seed ít nhất một triệu rows với skew gần production, không dùng distribution đồng đều giả tạo.
  2. Chọn query có equality, range và ordering; lưu baseline bằng EXPLAIN (ANALYZE, BUFFERS).
  3. Thử composite index, partial index và INCLUDE khi phù hợp; giải thích column order.
  4. Làm statistics cũ hoặc giảm statistics target để quan sát estimate sai, sau đó chạy ANALYZE và so plan.
  5. Đặt work_mem thấp trong session để tạo sort/hash spill rồi ghi temp I/O.
  6. Đo insert/update throughput, index size và cache impact; xóa index không còn justify.
Evidence: plans trước/sau, estimated-vs-actual rows, buffers/temp I/O, p50/p95 latency, TPS write và bytes mỗi index.
LAB 04 · PAGINATION · 60–90 PHÚT

Offset và keyset pagination

Mục tiêu: chứng minh latency và consistency behavior của hai pagination strategies.

Thực hiện

  1. Dùng dataset Lab 03 và stable ordering ORDER BY created_at DESC, id DESC.
  2. Benchmark page đầu, giữa và rất sâu bằng OFFSET; ghi rows scanned và buffers.
  3. Implement cursor chứa cả created_at lẫn unique tie-breaker id; encode cursor opaque và direction-aware.
  4. Insert/delete rows giữa hai page requests. Ghi rõ semantics mong muốn rồi kiểm tra duplicate/missing của mỗi strategy.
  5. Test nhiều rows cùng timestamp, reverse pagination và invalid/tampered cursor.
Evidence: latency theo page depth, execution plans, test duplicate/missing, cursor contract và query cho cả next/previous direction.
LAB 05 · CACHE-ASIDE · 90 PHÚT

Cache-aside và stale-data race

Mục tiêu: xây cache có ownership, freshness và failure behavior đo được.

Thực hiện

  1. Cache endpoint GET order với key gồm namespace/version/tenant, TTL và jitter.
  2. Đo hit, miss, origin latency và cache latency theo endpoint/key class.
  3. Update DB rồi invalidate; dùng barriers/delays để tái hiện reader set lại value cũ sau invalidation.
  4. Sửa race bằng versioned value hoặc event/outbox invalidation; xác định stale window còn lại.
  5. Thêm negative caching TTL ngắn và test object được tạo sau một negative hit.
  6. Tắt/làm chậm Redis; fallback DB phải có timeout, concurrency cap và không vượt request deadline.
Evidence: race timeline, stale read count trước/sau, hit ratio, source load, timeout trace và chứng minh tenant/auth key không bị lẫn.
LAB 06 · STAMPEDE + FAILOVER · 120 PHÚT

Stampede protection và Redis failover

Mục tiêu: giới hạn origin amplification và quan sát data-loss/client-recovery semantics.

Thực hiện

  1. Cho 100 requests đồng thời miss một hot key; đếm DB calls, peak concurrency và p99.
  2. Thêm per-process single-flight, sau đó chạy nhiều application instances để thấy giới hạn.
  3. Thử distributed lease hoặc stale-while-revalidate; kill holder và kiểm tra waiter deadline/fallback.
  4. Dựng primary/replicas với Sentinel hoặc một Redis Cluster local; tạo sustained writes rồi fail primary.
  5. Đo detection, promotion, client reconnect, replication lag và acknowledged writes bị mất/duplicate retry.
  6. Thử cache warmup có rate limit sau recovery thay vì nạp toàn bộ cùng lúc.
Evidence: requests-to-origin amplification ratio, latency distribution, failover timeline, old/new role, client errors và lost-write window.
LAB 07 · MVCC FORENSICS · 90–120 PHÚT

MVCC và autovacuum forensic

Mục tiêu: nối long transaction với dead tuples, vacuum progress và table growth.

Thực hiện

  1. Tạo table đủ lớn, mở transaction giữ snapshot và chạy workload update/delete ở session khác.
  2. Quan sát transaction age/xmin trong pg_stat_activity, live/dead tuples trong statistics và relation size.
  3. Chạy VACUUM/đợi autovacuum; dùng progress views/logs để giải thích vì sao tuples chưa reclaim được.
  4. Commit/rollback long transaction, chạy VACUUM và quan sát visibility/dead tuple thay đổi.
  5. Chứng minh regular VACUUM làm space reusable nhưng thường không trả file ngay cho OS; so với rewrite operation trong lab cô lập.
  6. Thử HOT-eligible và indexed-column update để so heap/index amplification.
Evidence: timestamped snapshots của activity/statistics/size, vacuum logs/progress, before-after plans và kết luận root cause.
LAB 08 · POSTGRESQL RECOVERY · 180+ PHÚT

PostgreSQL replication và PITR

Mục tiêu: đo RPO/RTO thực tế của physical standby và archived recovery.

Thực hiện

  1. Dựng primary/standby, tạo slot có retention guard và theo dõi sent/write/flush/replay LSN.
  2. Test read-after-write trên replica ở các mức lag khác nhau; implement route/wait timeout.
  3. Fail primary, fence node cũ, promote standby và redirect client; ghi timeline/timeline ID.
  4. Archive WAL, tạo base backup và restore point; thực hiện một lệnh DELETE có marker timestamp.
  5. Restore vào cluster cô lập tới thời điểm trước DELETE, validate data và application query.
  6. Làm hỏng một credential hoặc bỏ một WAL segment để chứng minh alert/runbook phát hiện restore gap.
Evidence: topology/config redacted, lag series, failover RPO/RTO, WAL archive inventory, recovery log và integrity/application checks.
LAB 09 · REDIS DURABILITY + CLUSTER · 180+ PHÚT

Redis durability và cluster incident

Mục tiêu: phân biệt process recovery, persistence durability, replica failover và cluster reshard behavior.

Thực hiện

  1. Chạy cùng write workload với RDB-only và AOF everysec; kill process/host simulation rồi đếm acknowledged records còn lại.
  2. Trigger snapshot/AOF rewrite dưới write load; đo fork duration, COW memory, latency và disk behavior.
  3. Tạo slow/disconnected replica, quan sát backlog/output buffer rồi buộc full resync.
  4. Với Sentinel, ghi SDOWN/ODOWN/election/promotion và client rediscovery; với Cluster, migrate slots và capture ASK/MOVED.
  5. Tạo hot slot/key để chứng minh thêm node không tự chia một key; rebalance và đo giới hạn còn lại.
  6. Restore persistence artifact vào instance cô lập, validate key count, sampled values và TTL.
Evidence: loss window theo mode, INFO/latency snapshots, peak RSS, failover/reshard logs, client retry outcomes và restore verification.

Definition of Done cho mỗi lab

Nguồn tham khảo