Cassandra DB

Petr Jůza
OpenWise Tech blog
Published in
6 min readOct 12, 2020

Kolegové ve firmě používají CassandraDB již nějaký čas a stala se tedy součástí našeho standardního technologického stacku. Já jsem se k ní dostal pořádně až v poslední době a rád bych zde uvedl několik poznatků a zkušeností, které mě na této DB zaujaly. Tento článek nemá za cíl souhrnně představit tuto DB, ani není návodem pro její použití — takových článků najdete jinde na internetu velké množství.

Pozn. naše zkušenosti a znalosti souvisí s verzemi 2.2.x a 3.x, v poslední době se ještě přidala ScyllaDB.

CAP teorem říká, že “pro distribuovaný počítačový systém je nemožné poskytovat současně více, než dvě ze tří následujících garancí:”

  • Konzistence (Consistency) — systém vrátí při každém čtení poslední zápis.
  • Dostupnost (Availability) — systém vrátí pro každý požadavek odpověď, nicméně bez garance, že jde o poslední zápis.
  • Tolerance rozdělení (Partition Tolerance) — systém zpracovává informace navzdory tomu, že došlo k rozdělení sítě (network partition), způsobené chybou komunikace mezi sub-systémy.

Z tohoto pohledu je CassandraDB AP databáze, tedy obětuje garanci Konzistence pro Dostupnost a Toleranci rozdělení. (pozn. úroveň konzistence, tzv. Consistency level, lze nastavovat pro jednotlivé operace čtení nebo zápisu a lze vynutit plně konzistentný přístup)

CassandraDB využívá následující strukturu pro uložení meta-informací, které popisují lokaci daného nodu oproti ostatním — jednak je to čistě informativní, ale zároveň se to používá k popisu replikační strategie a k nastavení využití clusteru, např. nastavení síťové topologie pomocí tzv. Snitches:

Cluster
— Data center(s)
— — Rack(s)
— — — Server(s)
— — — — Node(s)

Cluster obsahuje datová centra. Datové centrum obsahuje racky. Rack obsahuje servery. Server, přesněji řečeno Cassandra software, obsahuje (virtuální) nody (vnode). Základní datová jednotka se nazývá partition a ty jsou uloženy resp. replikovány na nody. Replikace jsou možné v rámci jednoho datového centra.

Množina nodů, které tvoří cluster, se označuje jako Cassandra ring. Každý node v ringu je zodpovedný za uložení dat podle definované partition key a replikačního faktoru. Virtuální nody (vnodes) nastavují vlastnictví dat, tedy jaké partition keys bude spravovat jaký node. K rozdělení se používá hash funkce, která určuje hash-rozmezí a tím určuje příslušnost dat k danému node.

Na každém node a pro každou partition jsou následující datové úložiště:

  • Commitlog — je to append only log, do kterého se ukládájí všechny změny než dojde k jejich propisu do memtable. Commitlog lze nastavit na jiné médium, že se má komprimovat, jak ma být velké atp. Je to první mechanismus jak zabránit ztrátě dat. Při startu nebo syncu dochází k synchronizaci.
  • Memtable je in-memory datová struktura, ve které dochází k bufferu write operací. Je to 1:1 k tabulce. Po uložení na disk se z ní stává SSTable.
  • SSTable je označení pro datový soubor, který Cassandra využívá pro ukládání dat. Zápisu předchází memtable nebo streamovaní dat z ostatních nodů. SSTable se kompaktují.

Při čtení dat je algoritmus složitější, hezky popsaný např. zde.

Více než u jiných DB se musíte seznámit s architekturou CassandryDB a jakým způsobem funguje. Tím nejzásadnějším pravidlem pro efektivní využití této DB je vytvoření takového datového modelu a způsobu práce s databází (zejména čtení dat), které budou podporovat koncepty této DB a nikoliv naopak. Pokud navrhnete špatně model nebo se budete doptávat “špatným” způsobem, pak performance nikdy nebude nijak oslnivá. Toto se píše všude a mohu potvrdit, že to tak skutečně je. Výborným vstupním zdrojem je přímo dokumentace ke CassandraDB: https://cassandra.apache.org/doc/latest/data_modeling/intro.html

Přikládám pár tipů, které jsem si z různých zdrojů poznamenal:

  • co nejvíce optimální rozmístění dat => vhodně zvolit primární klíč (PK)
  • minimalizace čtení z více partition, protože čtení dat z více partition je drahé, jsou umístěné na různých místech
  • potřebujeme vědet dopředu, jaké dotazy budeme dělat (query-driven modeling) a podle toho pak navrhneme uložení dat. Jeden dotaz k jedné tabulce (one query per table pattern)
  • obecné doporučení je mít max. 100k záznamů v jedné partition o velikosti max. 100 MB
  • požadované řazení dat je nutné si rozmyslet v čase návrhu modelu

Co se mě na Cassandře líbí nebo mě zaujalo:

  • je napsaná v Javě, takže pokud je někdo kovaný Javista jako já, tak potom většinu nástrojů na monitoring a ladění už znáte, hodně pomůže znalost fungování JVM a garbage collectoru konkrétně.
  • ScyllaDB je zajímavým vylepšením CassandryDB. Nejedná se pouze o přepis do C++, ale i o přepracování interních algoritmů s hlavním cílem a tou je vyšší performance (latence a zejména prostupnost). CassandraDB už sama o sobě je velice rychlá NoSQL databáze a u ScyllaDB se často uvádí ještě 5–10x větší zrychlení. Je také důležité uvést, že z pohledu aplikačního použití je ScyllaDB kompatibilní s CassandraDB: Scylla supports the CQL binary protocol version 3, so every Cassandra/CQL driver that implements it should work with Scylla. ScyllaDB také používáme na jednom projektu, právě z důvodu performance.
  • CassandraDB nepotřebuje nějaké super výkonné servery pro své nody, spíše naopak — její velká výhoda je v tom, že lze využívat “komoditní” hardware, navíc ji nevadí heterogenní prostředí.
  • databáze nabízí (skoro) neomezenou možnost horizontálního škálování s lineárním nárustem prostupnosti
  • CassandraDB nepoužívá častější model master-slave, ale nabízí přístup, kdy každý node je vlastně masterem (Multi-master replication) a data jsou mezi jednotlivými nody replikována. Každý node si pak hlídá své okolí, zda vše funguje jak má. CassandraDB má mechanismus, kterým určuje vlastnictví dat pro každý node. Na úrovni datového úložiště (přesněji řečeno keyspace) se určuje tzv. replikační faktor, tedy počet nodů, na které se mají daná data replikovat. Nejenom pro přístup k datům lze nastavit tzn. Quorum, které určuje počet nodů, které musí “potvrdit” resp. odpovědět na požadavek čtení. To je jeden ze způsobů, jak lze řídit úroveň konzistence, jak pro čtení, tak pro zápis.
  • CassandraDB nemá “Single Point of Failure”
  • každý záznam obsahuje kromě samotné hodnoty i timestamp, který slouží k seřazení příchozích změn a tedy pro vyhodnocení aktuálnosti dat a konzistence. Nic jako zámek zde neexistuje, data se čtou a zapisují v pořadí podle času, tedy zde platí vyrovnávací pattern “poslední vyhrává”. Každá operace (INSERT, ale i UPDATE nebo DELETE) vytváří nové záznamy. Z tohoto důvodu je nezbytné, aby čas na jednotlivých nodech byl synchronizovaný.
  • následující scénáře, které běžně používáme v relačních databázích, zde bývají typicky pomalé či složité na koordinaci, proto je vhodné se jim vyhnout a nebo vědět, proč se používájí — transakce přes více partitions (Cross partition transactions) nebo čtení dat z více partitions (Distributed joins) a nebo cizí klíče a referenční datová integrita (Foreign keys or referential integrity)
  • vzhledem k tomu, že je CassandraDB napsána v Javě, tak i primitivní datové typy odpovídají datovým typům v Javě. Z důvodů zpětné kompatibility je možné definovat pomocí Java tříd i komplexní datové typy, ale toto je dnes již deprecated. Pro vlastní datové typy lze využít tzv. user-defined type (UDT).
  • CassandraDB nepodporuje transakce tak jak je známe z relačních databází. Nejblíže k tomu je funkce Batch, která zajišťuje atomicitu a izolaci při zápisu dat, ideálně v rámci jedné partition nebo i více partitions za předpokladu, že množství dat není velké. Batch není určený pro hromadné nalévání dat.
  • u CassandraDB je nejtěžší vše správně navrhnout a nakonfigurovat, ale samotný provoz už tak náročný není (i když pokazit se může kdykoliv cokoliv), obecně se jedná o sledování jednotlivých nodů, zda nejsou dole a pak o sledování stavu dat, tj. zda jsou data optimálně uloženy v lokálních strukturách (zejména SSTables) pro každou partition a zda jsou správně synchronizována mezi jednotlivé nody. Bežnými operacemi pak jsou i přídávání a odebírání nodů v clusteru.
  • pro správu CassandryDB je k dispozici velké množství nástrojů, základními jsou zcela jistě nodetool, cassandra-stress a SSTable Tools přímo od “výrobce”. Cassandra-stress je výborný nástroj pro nějaké prvotní odladění správné konfigurace a performance. Pak mě zaujal nástroj CassandraReaper, který pomůže se spouštěním repair procesu na jednotlivých nodech v clusteru.

Na co je vhodné tedy CassandraDB použít?

  • obecně tam, kde je potřeba mnohem více zapisovat než číst a když už jsou data uložená, tak se moc nemění, ideálně vůbec.
  • CassandraDB se hodí tam, kde je potřeba zapisovat (a také číst) obrovské množství dat
  • z předchozího bodu lze odvodit řadu možných scénářů k použití, např. transakční logy, ukládání časových dat (time series data), různé hodnoty metrik nebo historická data obecně čehokoliv. Používáme Axway API gateway, která používá CassandraDB pro tzn. throtting, kdy si do DB ukládá všechny příchozí requesty a nad nimi se potom doptává na počet requestů pro určitý endpoint resp. URL za určitou časovou jednotku, aby vyhodnotila, zda nastavené limity throttlingu byly nebo nebyly překročeny.
  • její využití je hodně v datových analytikách, často je vidět ve skupině nástrojů jako Apache Spark nebo Hadoop.
  • CassandraDB je vhodná pro ukládání key-value dat všeho druhu a ve spojení s vysokou dostupností to je silný nástroj

--

--