Abstrakt: CQRS a Event Sourcing patří k nejčastěji diskutovaným, ale i nejčastěji nesprávně použitým návrhovým vzorům v podnikové architektuře. Nejde o nové trendy, ale o fundamentální principy distribuovaných systémů systematizované Gregem Youngem a Martinem Fowlerem. Tento článek shrnuje, kdy oba vzory přinášejí měřitelnou hodnotu, jakým způsobem je zavádět postupně a které domény jsou pro ně naopak nevhodné. Cílí na architekty a technické lídry, kteří zvažují migraci ze standardního CRUD modelu.
1. Limity tradičního CRUD přístupu
Klasický CRUD model se opírá o jeden datový schéma sloužící současně pro zápisy i čtení. To je dostatečné pro velké procento aplikací, ale naráží na limity v okamžiku, kdy systém musí zvládnout výrazně asymetrickou zátěž, komplexní reporting v reálném čase, regulatorní auditní stopu nebo souběžnou editaci dat více uživateli.
Typické symptomy překroku těchto limitů jsou kompromisy v datovém modelu (normalizace bránící výkonu na čtení, denormalizace ohrožující konzistenci na zápisu), těžko škálovatelné agregace nad transakční databází a nutnost zpětně rekonstruovat historii ze shadow tabulek nebo logů.
2. CQRS: oddělení odpovědností
Command Query Responsibility Segregation neznamená nutně dvě databáze. Jde o uznání, že příkazy (zápisy) a dotazy (čtení) mají různé požadavky a měly by mít vlastní modely.
Strana příkazů se optimalizuje pro konzistenci a validaci obchodních pravidel. Pracuje s normalizovaným modelem domény, používá ACID transakce a synchronně vrací odpověď na porušení pravidel. Strana dotazů je naopak optimalizovaná pro výkon čtení. Používá denormalizované, předpočítané pohledy, toleruje eventuální konzistenci a aktualizuje se asynchronně.
Implementaci lze zavádět ve dvou úrovních. Jednodušší varianta sdílí jednu databázi, ale udržuje oddělené repozitáře pro zápisy a čtení. Plná varianta používá zvlášť optimalizovanou databázi pro příkazy (například PostgreSQL nebo MongoDB) a samostatné úložiště pro dotazy (Elasticsearch, Redis, Cassandra), synchronizované přes události.
Praktickým příkladem je správa skladových zásob v e-commerce. Strana příkazů zpracovává rezervace a doplnění zboží přes agregát skladové položky s kontrolou zásob. Strana dotazů poskytuje rychlou kontrolu dostupnosti, reporty pro sklady a upozornění na nízké stavy z vlastních materializovaných pohledů.
3. Event Sourcing: události jako zdroj pravdy
Event Sourcing představuje obrat v přístupu k perzistenci. Místo aktuálního stavu se ukládá posloupnost neměnných událostí, které k němu vedly. Aktuální stav je odvozen jejich přehráním.
Tento přístup přináší tři praktické výhody. Za prvé úplnou obchodní historii včetně kontextu, což umožňuje časové dotazy ve stylu „jaký byl stav účtu k 31. prosinci“. Za druhé schopnost zpětně přepočítat stav po opravě chyby v logice bez ztráty auditní stopy. Za třetí možnost vytvářet nové projekce dat z existujících událostí bez migrace produkční databáze, což zjednodušuje vývoj nových reportů a analytiky.
Typickou doménou jsou bankovní transakční systémy. Každá transakce je zachycena jako neměnná událost, zůstatky se odvozují v reálném čase ze streamu událostí, regulatorní reporty vznikají filtrací podle typu události a fraud detection může analyzovat historické vzorce bez dotazů do živé databáze.
4. Klíčové implementační výzvy
Verzování událostí. Události jsou neměnné, ale obchodní logika se vyvíjí. Standardními řešeními jsou paralelní verze událostí, upcasting starších formátů při přehrávání nebo flexibilní JSON schéma s volitelnými poli.
Výkon při přehrávání. Pro velké agregáty se používají snapshoty stavu v pravidelných intervalech, takže přehrávání nemusí začínat od první události. Doplňkem jsou indexy nad event store podle časových oken nebo typů událostí a paralelní zpracování nezávislých streamů.
Souběžnost. Optimistický concurrency control založený na verzi posledního zaznamenaného eventu detekuje konflikty mezi paralelními zápisy. Konflikty se řeší retry logikou nebo doménovým rozhodnutím, eventuální konzistence read modelů je akceptovaným kompromisem.
Operační složitost. Provoz vyžaduje sledování zpoždění read modelů za event streamem, monitoring propustnosti zpracování událostí a nástroje pro replay i inspekci historie.
5. Volba technologií
Pro úložiště událostí připadají v úvahu specializovaná řešení (EventStoreDB, Apache Kafka, Amazon Kinesis) i adaptace tradičních databází (PostgreSQL s JSONB, MongoDB). Pro čtecí stranu se volí podle dominantního access patternu: Redis pro horká data, Elasticsearch pro full-text a analytiku, ClickHouse pro sloupcovou analytiku, Cassandra pro distribuované úložiště velkých objemů.
6. Vhodné a nevhodné domény
Vysokou návratnost přinášejí CQRS a Event Sourcing ve finančních službách (obchodování, bankovnictví, pojišťovnictví, účetnictví), kolaborativních platformách s vícenásobným zápisem do sdílených dokumentů a v e-commerce při řízení zásob a komplexních objednávkových workflow.
Naopak nevhodné jsou pro jednoduché obsahové aplikace, formulářové systémy s minimální obchodní logikou, prostředí s malými týmy bez zkušenosti s distribuovanými systémy a tam, kde jsou požadavky na striktní okamžitou konzistenci napříč všemi pohledy.
7. Postupná migrace
Doporučenou cestou je inkrementální zavádění. V první fázi stačí oddělit modely pro zápis a čtení nad společnou databází a ověřit přínos. Druhou fází je oddělení čtecí databáze a asynchronní synchronizace. Teprve ve třetí fázi se zavádí Event Sourcing, typicky na nekritické agregáty, kde lze dopady ověřit bez rizika.
Při integraci s legacy systémem se osvědčuje pattern strangler fig: nové zápisy směřují do nového systému, který generuje události, zatímco starý systém je postupně nahrazován funkcionalitu po funkcionalitě. Anti-corruption vrstva izoluje nový model od historického schématu.
Závěr
CQRS a Event Sourcing jsou specializované nástroje, ne univerzální řešení. Přinášejí výrazné benefity tam, kde existuje silná asymetrie mezi zátěží na čtení a zápisu, kde je auditní stopa regulatorním požadavkem nebo kde komplexní obchodní procesy přirozeně vyžadují událostní pohled. V opačných případech se z nich stává drahý technický dluh.
Rozhodovací kritéria zahrnují charakter domény, zralost týmu v oblasti distribuovaných systémů, dostupnost provozního zázemí a schopnost organizace investovat do monitoringu a debuggovacích nástrojů. Začněte vždy s nejmenším smysluplným krokem, ověřte přínos měřitelnými ukazateli a teprve poté rozšiřujte zavedení na další části systému.
Doporučené zdroje:
- Martin Fowler: CQRS, Event Sourcing
- Greg Young: CQRS Documents
- EventStoreDB documentation
- Microsoft: CQRS Journey
- Apache Kafka documentation