Relační databáze nás provázejí celou kariérou. Ale co když potřebujete zapisovat miliony událostí za sekundu, data replikovat napříč datovými centry a přitom garantovat dostupnost 99,99 %? PostgreSQL ani Oracle na to nestačí. Začali jsme experimentovat s Apache Cassandrou.
Proč ne relační databáze?¶
Pro telco klienta jsme stavěli systém pro sběr CDR záznamů (Call Detail Records). Požadavky: 50 000 zápisů za sekundu, retence 2 roky, přístup k datům z dvou geograficky oddělených lokalit. Klasický přístup — PostgreSQL s partitioningem — narazil na limity vertikálního škálování. Přidávat RAM a CPU na jeden server má svůj strop.
Cassandra nabízí horizontální škálování — přidáte nový uzel do clusteru a data se automaticky přerozdělí. Žádný single point of failure, žádný master node. Každý uzel je rovnocenný.
Architektura: ring a partitioning¶
Cassandra organizuje uzly do logického kruhu (ring). Každý řádek dat má partition key, ze kterého se vypočítá hash. Hash určí, na který uzel data patří. S replikačním faktorem 3 se každý řádek uloží na tři uzly — pokud jeden spadne, data jsou stále dostupná.
CREATE KEYSPACE telco_cdr
WITH replication = {
'class': 'NetworkTopologyStrategy',
'dc_prague': 3,
'dc_brno': 3
};
CREATE TABLE telco_cdr.call_records (
phone_number text,
call_date date,
call_time timestamp,
duration int,
called_number text,
cell_id text,
PRIMARY KEY ((phone_number, call_date), call_time)
) WITH CLUSTERING ORDER BY (call_time DESC);
Klíčový je návrh partition key. Zvolili jsme kompozitní klíč
(phone_number, call_date) — každá partice obsahuje záznamy jednoho
čísla za jeden den. To zajišťuje rovnoměrné rozložení dat a efektivní dotazy
typu „ukaž mi hovory čísla X za datum Y”.
Tunable consistency¶
Na rozdíl od relačních databází, kde máte ACID transakce, Cassandra nabízí nastavitelnou konzistenci. Pro každý dotaz volíte úroveň:
- ONE — odpověď z jednoho uzlu, nejrychlejší, ale riskujete zastaralá data
- QUORUM — odpověď z většiny replik, dobrý kompromis
- ALL — odpověď ze všech replik, nejpomalejší, ale silná konzistence
- LOCAL_QUORUM — quorum v rámci jednoho datového centra, ideální pro geo-replikaci
Pro zápisy CDR záznamů jsme zvolili LOCAL_QUORUM — data se potvrdí lokálně a asynchronně replikují do druhého DC. Pro čtení analytických reportů používáme také LOCAL_QUORUM, čímž garantujeme konzistenci čtení po zápisu v rámci jedné lokality.
Data modeling: query-first přístup¶
Největší mentální posun oproti relačním databázím: v Cassandře modelujete data podle dotazů, ne podle entit. Normalizace neexistuje. Duplikace dat je normální a žádoucí.
Pokud potřebujete stejná data zobrazit dvěma různými způsoby (podle čísla a podle buňky sítě), vytvoříte dvě tabulky se stejnými daty, ale různými partition keys. Zapisujete do obou současně. Disk je levný, latence dotazu drahá.
Operace v produkci¶
Compaction¶
Cassandra zapisuje data do immutable souborů (SSTables). Periodicky je slučuje proces compaction. Zvolili jsme DateTieredCompactionStrategy — optimální pro time-series data, kde se starší záznamy nemění. Compaction je CPU a I/O náročná operace, plánujeme ji mimo špičku.
Repair¶
Pokud uzel byl offline a zmeškal zápisy, data na něm mohou být neaktuální.
Příkaz nodetool repair synchronizuje data mezi replikami. Spouštíme
ho jednou týdně na každém uzlu — je to nutná údržba, ale zatěžuje cluster.
Monitoring¶
Cassandra exportuje metriky přes JMX. Sledujeme zejména: read/write latency (p99 pod 10 ms), compaction pending (nemá narůstat), heap usage a tombstone count. Příliš mnoho tombstones (mazání v Cassandře) zpomaluje čtení — proto preferujeme TTL nad explicitním DELETE.
Cassandra vs. MongoDB¶
Obě jsou NoSQL, ale řeší jiné problémy. MongoDB exceluje v flexibilním schématu a ad-hoc dotazech — je bližší relační databázi. Cassandra vyniká v zápisovém výkonu, horizontálním škálování a multi-DC replikaci. Pro naše CDR záznamy (write-heavy, time-series, geo-distribuované) byla Cassandra jasná volba.
Výsledky¶
Cluster šesti uzlů (3 v každém DC) zpracovává 80 000 zápisů/s s p99 latencí pod 5 ms. Čtení analytických dotazů (hovory jednoho čísla za měsíc) trvá 15–30 ms. Data se replikují mezi Prahou a Brnem s latencí pod 50 ms. Za šest měsíců provozu jsme měli nulový výpadek — i při plánované údržbě (rolling restart) cluster běžel bez přerušení.
Cassandra není náhrada relační databáze¶
Cassandra je specializovaný nástroj pro specifické use cases: write-heavy workloady, time-series data, geo-distribuované systémy. Pokud potřebujete JOINy, ad-hoc dotazy nebo ACID transakce, zůstaňte u PostgreSQL.
Ale pokud vaše požadavky odpovídají — a věříme, že s rostoucím objemem dat bude takových projektů přibývat — Cassandra je výjimečně spolehlivé řešení.