Împărțirea și replicarea bazelor de date
Împărțirea și replicarea bazelor de date
1) De ce aveți nevoie de ea
Când upgrade-ul vertical al bazei de date abută împotriva CPU/IO/RAM sau un cluster devine SPOF, replicarea (pentru citește/HA) și sharding (pentru scriere/distribuție de date) vin. Obiective:- Debit (scrieți creșterea orizontală QPS).
- Disponibilitate (failover rapid, nici un singur punct de eșec).
- Localizarea datelor (multi-regiune, latență scăzută).
- Izolarea vecinilor zgomotoși (chiriași fierbinți/chei fierbinți).
2) Termeni de bază și modele de consistență
Primar/Lider ↔ Replica/Adept: scrie pe lider, citiți pe replici.
Replicare sincronă: confirmarea tranzacției după scrierea pe nodurile N (RPO scăzut, latență mai mare).
Asincron: liderul comite și trimite jurnalul mai târziu (RPO> 0, latență scăzută).
Cvorum (Raft/Paxos): scrierea la majoritatea nodurilor; un jurnal, lider automat.
Citire după scriere: citire garantată a înregistrărilor sale (a se vedea § 5).
Citim PAC în astfel de vânzări: în cazul unor probleme de rețea, alegeți consistența (CP) sau disponibilitatea (AP) pentru operațiuni critice, combinând adesea niveluri pe căi diferite.
3) Replicare: Opțiuni și practici
3. 1 Fizic și logic
Fizic (WAL/redo/binlog): mai aproape de jurnalul de bloc, simplu și rapid; limitată la topologie/versiune omogenă.
Logic: flux DML/DDL la nivelul rândului/mesei; permite replici parțiale, migrații cross-version, CDC pentru DWH/streaming.
3. 2 Configurare şi gestionare
Decalajul monitorului (timp/octeți/LSN).
Limitați feedback-ul la cald și cererile lungi de replici (pentru a nu bloca ASPIRUL/curățarea).
Pentru MySQL - GTID și orchestrator; для PostgreSQL - Sloturi patroni/replicare, synchronous_standby_names.
sql
-- на лидере
ALTER SYSTEM SET synchronous_commit = 'on';
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 (standby_a, standby_b)';
SELECT pg_reload_conf();
MySQL GTID (ID tranzacție):
sql
SET GLOBAL enforce_gtid_consistency = ON;
SET GLOBAL gtid_mode = ON; -- перезапуск
CHANGE MASTER TO MASTER_AUTO_POSITION=1;
3. 3 Topologii
1→N (lider → replica) + cascade (replica fuzionează în continuare).
Multi-primar (activ-activ) - evitați în OLTP fără gestionarea strictă a conflictelor.
Cluster de cvorum (Raft) - suplimente GandachDB/Yugabyte/PG-Raft.
4) Citiți/scrieți Split și rutare
Întotdeauna scrie ca un lider; citiți din indicii, dar luați în considerare lag.
Strategii de citire după scriere:1. Stickiness sesiune: După o înregistrare de succes, clientul citește de la lider în timpul „Δ T”.
2. Poarta LSN/GTID: clientul spune „Vreau să nu îmbătrânesc LSN = X”, routerul trimite la replica, al cărei LSN ≥ X.
3. Stale-ok: unele interogări permit date vechi (directoare/benzi).
Instrumente: PgBouncer/Pgpool-II (Postgres), ProxySQL/MaxScale (MySQL), Vitess (shard routing).
Exemplu de poartă LSN (idee): salvați 'pg _ current _ wal _ lsn ()' într-un antet/cookie HTTP și solicitați routerului să replice cu 'pg _ last _ wal _ replay _ lsn () ≥ LSN'.
5) Strategii de Sharding
5. 1 Selecție cheie
Cheia asigură uniformitatea și localitatea solicitărilor:- Hash by 'tenant _ id'/' user _ id' - uniform, dar privează scanările în interval.
- Interval în timp/ID - mare pentru seria de timp/arhivă, dar risc hot-shard.
- Hashing consecvent - face ușor de a adăuga/elimina cioburi.
- Directory/lookup table - flexibil (orice algoritm), dar un alt tabel/cache.
5. 2 Modele
Shared-nimic: fiecare ciob este o bază de date separată/cluster, aplicația știe rutare.
Middleware-sharding: Vitess (MySQL), Citus (Postgres), Proxy-level ascunde topologia.
Federația: separarea domeniilor de date pe servicii (catalog, plăți, auth).
5. 3 chei compozite
Utilizați spațiul cheie: '{chiriaș}: {entitate}: {id}' și stocați-l în aplicație și memoria cache. Для Postgres - partiționarea hash + subpartiția LIST/RANGE.
Partiționarea PostgreSQL (fragment):sql
CREATE TABLE orders (
tenant_id int,
id bigint,
created_at timestamptz,
...,
PRIMARY KEY (tenant_id, id)
) PARTITION BY HASH (tenant_id);
CREATE TABLE orders_t0 PARTITION OF orders FOR VALUES WITH (MODULUS 16, REMAINDER 0);
--... t1..t15
6) generarea de ID-uri
Evitați „fierbinte” auto-incremente monotone pe sharding.
Utilizați ID-ul de tip fulg de zăpadă pe 64 de biți (timp + regiune + ciob + seq) sau ULID/KSUID (monotonie și distribuție).
Для Postgres - secvență per ciob; pentru MySQL - auto_increment_increment/offset (diferite compensări pe liderii de cioburi).
7) Oversharing online și migrații
Principii cheie: scriere dublă, idempotență, rutare dublă temporară.
Etape (generalizate):1. Adăugați un nou ciob/cluster.
2. Activați citirea duală (verificarea consistenței).
3. Includeți dual-write (în ambele cioburi), înregistrați discrepanțe.
4. Backfill date istorice (loturi, replicare logică/CDC).
5. Comutați „sursa adevărului” la un ciob nou; lăsați sincronizarea „coadă”.
6. Opreşte-l pe cel vechi.
Instrumente: Vitess Resharding, Citus muta cioburi, pg_logical/pgoutput, Debezium (CDC), gh-ost/pt-online-schema-schimbare (DDL fără încuietori).
8) Multi-regiune și geo-distribuție
Lider-adept pe regiune: citeşte local, scrie - prin liderul global (model simplu, dar transregional RTT).
Multi-lider: înregistrarea în ambele regiuni - aveți nevoie de conflict-mering (timestamp/version/CRDT).
True distribuit SQL (Raft): GândacDB/Yugabyte - datele sunt „lipite” în regiune, interogările merg la cvorumul local.
- Bani/comenzi - CP (cvorum/leader), directoare/benzi - AP (cache, eventual).
- Planificați întotdeauna scrimă (chei unice/versioning) cu un posibil creier divizat.
9) Coerența în practică
Read-your-scrie: liderul sau tac care „prins” cu LSN/GTID.
Monotonic spune: „nu mai vechi” decât ultimul LSN citit.
Scrie-conflict de control: "SELECTAȚI... PENTRU UPDATE ', versiuni (' xmin '/' rowversion '), UPSERT cu verificarea versiunii.
Idempotence: chei de idempotence la plăți/evenimente.
10) Observabilitate, SLO și alerte
Lag replica: timp (secunde), LSN distanță (octeți), seconds_behind_master (MySQL).
Rollback-uri/conflicte forțate, erori de replicare.
p95/p99 latență по traseu (citiți liderul vs replica, scrie).
Throughput: TPS/încuietori/tabele conturate pe rând.
Bloat/VACUUM (PG), InnoDB buffer pool hit ratio (MySQL).
Tablouri de bord: încărcătură per ciob, cioburi „fierbinți”, distribuție de chei.
11) Copii de rezervă, PITR și DR
Copie de rezervă completă + WAL/binlog pentru PITR (point-in-time recovery).
Stocați într-o altă regiune/cloud, restabiliți testele în mod regulat.
Pentru cioburi, o „felie” consistentă (coordonare de timp/LSN) sau idempotență aplicativă asupra recuperării.
RPO/RTO sunt scrise și testate în zilele de joc.
bash pg_basebackup -D /backups/base -X stream -C -S slot_replica_1 архивация WAL через archive_command или pgBackRest/Barman
12) Securitate și acces
Segmentarea prin VPC/ACL, mTLS prin proxy.
Roluri/granturi pe principiul drepturilor minime; utilizatori individuali per ciob/rol.
Audit DDL/DCL, limite privind cererile „grele” pe replici.
Criptare în repaus (KMS) și în tranzit (TLS).
Buton de panică: Global „READ ONLY” pe durata incidentului/investigației.
13) Unelte și cărămizi
PostgreSQL: Patroni (HA), PgBouncer (pooling/RO-routing), repmgr, pgBackRest/Barman (бэкап), Citus (шардинг), Replicare pglogică/logică, pgbadger/pg_stat_statements.
MySQL: Orchestrator (topologii/auto-failover), ProxySQL/MaxScale (rutare), Percona XtraBackup (backup), Group Replication/InnoDB Cluster, Vitess (sharding/resharding).
Distribuit SQL: gandacDB, YugabyteDB (cvorum, built-in sharding/geolocation).
CDC: Debezium + Kafka/Pulsar pentru evenimente/ETL.
14) Anti-modele
Singur-primar fără auto-failover și fără teste DR.
„Magic” read-split excluzând lag → erori fantomă/bug-uri suspecte.
Sharding „de dragul de sharding”: complicație prematură în loc de scară verticală/indici/cache.
Gama fierbinte (interval de timp) fără timp-găleată/hash-sare → un ciob se topește.
Tranzacția globală 2PC pe partea de sus a zeci de cioburi în OLTP - cozi p99 ridicate și încuietori frecvente.
Lipsa de dual-write/dual-read în timpul migrațiilor → pierderi/în afara sincronizării.
DDL în prod fără instrumente online și fără steaguri caracteristică de compatibilitate.
15) Lista de verificare a implementării (0-60 zile)
0-15 zile
Definiți DB SLO, RPO/RTO.
Activați replicarea, monitorizarea decalajelor, backup-urile de bază + PITR.
Introduceți routerul (PgBouncer/ProxySQL) și politica de citire după scriere.
16-30 zile
Alegeți o strategie de sharding, descrieți cheile și schemele.
Pregătiți instrumente de supraîncărcare (Vitess/Citus/CDC).
Director de servicii/tabele marcate "read-stale-ok" vs "strict'.
31-60 zile
Rulați pilot-ciob, dual-citit și rambursare.
Ziua jocului: eșecul liderului, recuperarea de la PITR, comutarea regiunii.
Automatizați cheia ciobului fierbinte și raportarea neuniformă.
16) Valorile maturității
Replica lag p95 <țintă (de ex. 500 ms) pentru citiri critice.
Teste DR de succes ≥ 1/trimestru (restabilirea ≤ RTO, pierderea ≤ RPO).
Distribuția sarcinii prin cioburi: dezechilibru <20% prin QPS/stocare.
Procentul de cereri cu o coerență strictă rutate corect = 100%.
Zero-pierderi de date în incidente care necesită garanții CP (bani/ordine).
DDL online/migrare fără timpi morți, cu steaguri de compatibilitate.
17) Exemple de rețete
Hash-sare pentru intervalul de timp (pentru a nu încălzi un ciob):sql
-- вычисляйте bucket = hash(user_id) % 16, храните (bucket, created_at)
PARTITION BY LIST (bucket) SUBPARTITION BY RANGE (created_at)
Citeşte-mi-scrie middleware (pseudocodul):
python lsn = db.leader_query("SELECT pg_current_wal_lsn()")
ctx.sticky_until = now()+5s ctx.min_lsn = lsn в роутере чтений: выбираем реплику с last_lsn >= ctx.min_lsn, иначе лидер
Vitess VSchema (fragment):
json
{
"tables": {
"orders": { "column_vindexes": [{ "column": "tenant_id", "name": "hash" }] }
}
}
18) Concluzie
Sharding și replicarea nu sunt doar o tehnică, ci și procese: rutare conștientă de consistență, disciplină de migrare (dual-write/read, backfill), teste DR regulate și observabilitate lag/hot shard. Începeți cu un leader→replica simplu + citire-după-scriere, apoi adăugați sharding în cazul în care profilul de sarcină necesită într-adevăr. Utilizați platforme gata făcute (Vitess/Citus/Distributed SQL) și păstrați datele critice pentru afaceri în modul CP - în acest fel baza va înceta să fie un blocaj și va deveni o bază elastică previzibilă a platformei.