Barcha loyihalarTugallangan

PG Resilience Lab

PostgreSQL klasterini 10 xil usulda buzib, RTO, RPO va ledger yaxlitligini o'lchagan HA/DR laboratoriyasi

Bu loyiha nimani isbotlaydi

  • 10 nosozlik × 3 run: tasdiqlangan 91 700 o'tkazmadan 0 tasi yo'qoldi, 0 tasi ikki marta qo'llandi, ledger doim muvozanatda
  • Sinxron replikatsiyani kutayotgan commit'ni cancel qilish "muvaffaqiyat" deb javob berib uni yo'qotishini o'lchadim (72 qator); fencing terminate'ga o'tkazildi, 0 yo'qotish
  • 17 → 18 upgrade'ning ikki usuli: pg_upgrade --link 22.6 s, logical replication + HAProxy cutover 2.4 s yozish uzilishi
  • Xato DROP TABLE'ni pg_waldump bilan topilgan xid'dan oldingacha PITR bilan tikladim, mediana 32 s
Rol
Yakka: klaster dizayni, nosozlik kiritish va o'lchovni avtomatlashtirish, tahlil, 6 ta ADR va koreyscha runbook
Muddat
2026.10 – 2026.10
Texnologiyalar
  • PostgreSQL
  • repmgr
  • pgBackRest
  • HAProxy
  • Docker
  • k6
  • Bash
  • Python
  • NestJS

Asosiy raqamlar

Ko'rsatkichQiymatTuriDalil
Tasdiqdan keyin yo'qolgan o'tkazmalar (30 run)0 / 91,700O'lchanganDalilni ko'rish
RTO medianasi · primary kill -97,07 sO'lchanganDalilni ko'rish
RTO medianasi · 45 s tarmoqdan uzilish27,91 sO'lchanganDalilni ko'rish
RTO medianasi · split-brain28,2 sO'lchanganDalilni ko'rish
RTO medianasi · DROP TABLE → PITR32,03 sO'lchanganDalilni ko'rish
17 → 18 logical replication cutover yozish uzilishi2,43 sO'lchanganDalilni ko'rish
17 → 18 pg_upgrade --link yozish uzilishi22,6 sO'lchanganDalilni ko'rish
cancel bilan bo'shatilib, muvaffaqiyat deb javob berilgan va yo'qolgan commit'lar72 / 620O'lchanganDalilni ko'rish
Xavfsizlik tekshiruvlari o'tdi18 / 18O'lchanganDalilni ko'rish

Hal qilinadigan muammo

Ko'p HA sozlamalari "sozlandi" bilan tugaydi: primary haqiqatan o'lganda yozish necha soniyada qaytishi va tasdiqlangan tranzaksiya yo'qolmasligi o'lchanmaydi. Bu laboratoriya LedgerCore'ga soniyasiga 20 ta o'tkazma yuborib turib 10 xil nosozlikni har birini 3 martadan kiritadi: primary to'xtashi, kill -9, server o'chishi va qayta yonishi, tarmoqdan uzilish, WAL diski to'lishi, data papkasining o'chirilishi, jadval faylining yo'qolishi, xato DROP TABLE va split-brain. Har run'da RTO, tasdiqdan keyin yo'qolgan o'tkazmalar (RPO), ikki marta qo'llanish va double-entry invarianti hisoblanadi.

Arxitektura

3 ta PostgreSQL 17 tugun (repmgr 5.5, 1 primary + 2 standby) va witness replikatsiya tarmog'ida, LedgerCore API va HAProxy ilova tarmog'ida turadi; faqat replikatsiya tarmog'ini uzish mijozlar eski primary'ga yetib boradigan split-brain'ni takrorlaydi. synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)'. Har tugundagi health agent (:8008) /primary'ga faqat tugun recovery'da bo'lmasa, fence qilinmagan bo'lsa va 3 soniya ichida javob bergan sinxron standby bo'lsa 200 qaytaradi; HAProxy buni har soniyada tekshiradi. Yakkalangan primary read-only bo'lib, sessiyalarni terminate qiladi. Backup TLS server rejimidagi alohida pgBackRest ombor xostida (asinxron WAL arxivlash, backup standby'dan), barcha ulanishlar lab CA'sidan verify-full TLS. runner konteyneri k6 yuki, nosozlik kiritish, tiklash va tahlilni avtomatik bajaradi.

Ma'lumotlar modeli

Asosiy cheklovlar va indekslar

  • synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)': bitta standby yo'qolsa ham yozish davom etadi
  • HAProxy :5000 faqat sinxron kvorumi tirik primary'ga yo'naltiradi
  • Barcha ulanishlar hostssl, verify-full va scram-sha-256; tarmoqdan superuser kirishi rad etiladi; credcheck kamida 16 belgi
  • ledger_app roli: statement_timeout 5 s · lock_timeout 2 s · idle_in_transaction_session_timeout 10 s

Asosiy loyihaviy qarorlar

ADR-0001 repmgr + witness

Vaziyat
3 tugunda avtomatik failover kerak edi va kursdagi vositalar bilan mexanizmni bevosita boshqarmoqchi edim.
Qaror
repmgr 5.5 + witness, primary_visibility_consensus, standby_disconnect_on_failover, bolalar uzilsa primary fence
Evaziga
DCS lock yo'q, split-brain himoyasini kvorum yo'naltirish va fencing bilan to'ldirish kerak

ADR-0002 Sinxron kvorum ANY 1

Vaziyat
FIRST 1 (pg2) kabi bitta sinxron standby belgilansa, pg2 to'xtaganda barcha yozishlar to'xtaydi.
Qaror
synchronous_standby_names = 'ANY 1 (pg1, pg2, pg3)'
Evaziga
pg2 25 s to'xtaganda FIRST 1: 12 119 muvaffaqiyatsiz urinish va 213 ta voz kechilgan o'tkazma, ANY 1: 0. Ikkala standby ham uzilsa yozish baribir to'xtaydi

ADR-0003 Kvorumni tekshiradigan HAProxy health check

Vaziyat
Birinchi run'larda yakkalanib qaytgan primary o'zini fence qilgunicha taxminan 18 s HAProxy'ga primary sifatida ko'rindi.
Qaror
/primary faqat recovery'da emas, fence qilinmagan va 3 s ichida javob bergan sinxron standby bo'lsa 200
Evaziga
Barcha standby sekin bo'lsa, sog'lom primary ham yozishdan chiqadi; bu holatda sinxron replikatsiya commit'larni baribir to'sib turgan bo'ladi

ADR-0006 Sinxron kutishda cancel emas, terminate

Vaziyat
Bo'lingan primary'da sinxron standby'ni kutayotgan sessiyalarni tozalash kerak, statement_timeout esa bu kutishni uzmaydi.
Qaror
Fencing faqat pg_terminate_backend ishlatadi, runbook SyncRep kutishlarida cancel'ni taqiqlaydi
Evaziga
Mijoz ulanish xatosini oladi va qayta urinishi kerak; LedgerCore idempotency key bilan xavfsiz qayta yuboradi

Oldin va keyin

Oldinpg_cancel_backend · acked 620 rows → 72 lostDalilni ko'rish
Keyinpg_terminate_backend · acked 2,460 rows → 0 lostDalilni ko'rish
Nima o'zgartirildi
Bo'linish paytida sinxron replikatsiyani kutayotgan commit'larni pg_cancel_backend bilan bo'shatish PostgreSQL'ni ularni muvaffaqiyatli deb javob berishga majbur qiladi va failover'dan keyin qatorlar yo'qoladi. Fencing endi faqat pg_terminate_backend ishlatadi, runbook cancel'ni taqiqlaydi (ADR-0006).

Nosozlik tarixi

Belgi
ack-leak tajribasi paytida ikkala standby ham promote bo'lolmadi, logda recovery ended before configured recovery target was reached qoldi.
Sabab
09-ssenariydagi PITR postgresql.auto.conf'da recovery_target_xid'ni qoldirgan, keyin klonlangan har bir standby uni ko'chirgan; shuning uchun har promote allaqachon o'tib ketgan recovery target'ni kutgan.
Yechim
PITR'dan so'ng darhol ALTER SYSTEM RESET recovery_target_* bajariladi, clone va rejoin ham recovery_target sozlamalarini ehtiyot uchun o'chiradi.
Takrorlanmasligi uchun
09-ssenariyning tiklash bosqichi PITR'dan keyin yangi to'liq backup oladi; tuzatishdan keyingi 30 run'lik kampaniyada (3 ta PITR bilan) bu xato qaytmadi.

Test va sifat

Testlar soni
—
Qamrov
—
CI
—
Test vositalari
장애 시나리오 10종 × 3회, 실험 8종, 보안 점검 18개(security/run.sh), bash -n, LedgerCore 단위 테스트 3개(연결 끊김 수정)

Deploy va ekspluatatsiya

Deploy muhiti
Bitta xostda Docker Compose. Windows'da .\lab.ps1 init tasodifiy parollar bilan .env yaratadi, .\lab.ps1 up esa image build, sertifikatlar, klaster bootstrap, birinchi to'liq backup va pg_cron vazifalarini bir buyruqda bajaradi.
Backup
Alohida pgBackRest ombor xosti (TLS server rejimi, zstd), asinxron WAL arxivlash, to'liq backup haftada, differential har kuni, incremental har 4 soatda, standby'dan. Har kuni oxirgi backup vaqtinchalik tiklanib, ledger yaxlitligi va checksum tekshiriladi (tiklash 1.8 s + recovery 1.4 s, buzilish 0). S3 repo2 (aes-256-cbc) sozlangan, lekin o'lchanmagan.
Rollback
pg_upgrade muvaffaqiyatsiz bo'lsa, eski 17 data papkasi avtomatik qaytariladi. .\lab.ps1 baseline buzilgan tugunlarni rejoin yoki qayta quradi va pg1'ni yana primary qiladi.
Monitoring
Har tugunda health agent (:8008), HAProxy stats (:8404), barcha tugunlardagi repmgr hodisalari nosozlik vaqtiga nisbatan timeline'ga yig'iladi. Sinxron kvorum, WAL arxivlash xatolari va jadval bloat'i PG Insight'da kuzatildi.

Skrinshotlar

Cheklovlar va xulosalar

Hozirgi cheklovlar

  • Barcha konteynerlar bitta xostda: laboratoriya haqiqiy server nosozligini emas, HA mexanizmlarini (aniqlash, saylash, fencing, yo'naltirish, tiklash) tekshiradi; sinxron replikatsiya narxi ham haqiqatdagidan arzon ko'rinadi.
  • Raqamlar 2 vCPU Linux sandbox'da xuddi shu paketlarning Ubuntu asosidagi o'rinbosar image'lari bilan o'lchandi; repodagi Dockerfile postgres:17-bookworm va PGDG paketlarini ishlatadi.
  • repmgr'da DCS leader lock yo'q, shuning uchun split-brain himoyasi sinxron kvorum, kvorumga asoslangan yo'naltirish va soft fence birikmasi; Patroni + etcd kuchliroq kafolat beradi.
  • S3 ombori (repo2) sozlangan, lekin o'lchovlarda ishlatilmagan; PgBouncer yo'q.

Qayta qursam

  • Xuddi shu ssenariylarni Patroni + etcd'da ishlatib, RTO va split-brain xatti-harakatini repmgr bilan solishtiraman.
  • Sinxron replikatsiyaning haqiqiy tarmoq narxini o'lchash uchun kamida ikki serverda ishlataman.

Asosiy kod

Hozirgi holat va keyingi qadamlar

30 ta run'da muvaffaqiyatli javob olgan 91 700 ta o'tkazmaning birortasi yo'qolmadi, ikki marta qo'llanmadi va ledger muvozanati buzilmadi. RTO medianasi: jarayon nosozliklarida 6.7~7.5 s, server o'chishida 24.7 s, tarmoqdan uzilishda 27.9 s, split-brain'da 28.2 s, PITR'da 32.0 s, data papkasi o'chirilganda 35.9 s. Birinchi run'lar ma'lumotni xavf ostiga qo'ygan yoki klaster o'zini tiklay olmagan 12 ta muammoni ochdi va hammasi tuzatildi, jumladan DB ulanishi uzilganda LedgerCore API jarayoni butunlay qulaydigan bug. 17 → 18 upgrade'da pg_upgrade --link 22.6 s, logical replication + HAProxy cutover 2.4 s yozish uzilishi berdi, ikkalasida ham yo'qotish 0.