Cassandra. Jak nezemřít, když znáte pouze Oracle

Čau Habr.

Jmenuji se Misha Butrimov, ráda bych vám řekla něco málo o Cassandře. Můj příběh bude užitečný pro ty, kteří se s NoSQL databázemi nikdy nesetkali – má spoustu implementačních funkcí a úskalí, o kterých musíte vědět. A pokud jste neviděli nic jiného než Oracle nebo jakoukoli jinou relační databázi, tyto věci vám zachrání život.

Co je na Cassandře tak dobrého? Je to databáze NoSQL navržená bez jediného bodu selhání, která se dobře škáluje. Pokud potřebujete přidat pár terabajtů pro nějakou databázi, jednoduše přidáte uzly do kruhu. Rozšířit to do jiného datového centra? Přidejte uzly do clusteru. Zvýšit zpracované RPS? Přidejte uzly do clusteru. Funguje to i v opačném směru.

Cassandra. Jak nezemřít, když znáte pouze Oracle

V čem je ještě dobrá? Jde o vyřízení spousty požadavků. Ale kolik je hodně? 10, 20, 30, 40 tisíc požadavků za vteřinu není moc. 100 tisíc požadavků za sekundu na nahrávání - taky. Existují společnosti, které uvedly, že udržují 2 miliony požadavků za sekundu. Asi tomu budou muset věřit.

A v zásadě má Cassandra od relačních dat jeden velký rozdíl – není jim vůbec podobná. A to je velmi důležité mít na paměti.

Ne všechno, co vypadá stejně, funguje stejně

Jednou za mnou přišel kolega a zeptal se: „Tady je dotazovací jazyk CQL Cassandra a má příkaz select, má kde, má a. Píšu dopisy a nejde to. Proč?". Zacházet s Cassandrou jako s relační databází je perfektní způsob, jak spáchat násilnou sebevraždu. A já to nepropaguji, v Rusku je to zakázané. Prostě něco špatně navrhneš.

Například k nám přijde zákazník a řekne: „Pojďme vytvořit databázi pro televizní seriály nebo databázi pro adresář receptů. Budeme tam mít jídla nebo seznam televizních seriálů a herců v něm.“ Radostně říkáme: "Pojďme!" Stačí poslat dva bajty, pár znaků a je hotovo, vše bude fungovat velmi rychle a spolehlivě. A vše je v pořádku, dokud zákaznice nepřijdou a neřeknou, že hospodyňky řeší i opačný problém: mají seznam produktů a chtějí vědět, jaké jídlo chtějí vařit. Jste mrtví.

Cassandra je totiž hybridní databáze: současně poskytuje klíčovou hodnotu a ukládá data do širokých sloupců. V Javě nebo Kotlinu by se to dalo popsat takto:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Tedy mapu, která obsahuje i seřazenou mapu. První klíč k této mapě je klíč Row nebo Partition key - rozdělovací klíč. Druhý klíč, který je klíčem k již seřazené mapě, je klíč Clustering.

Pro ilustraci distribuce databáze nakreslíme tři uzly. Nyní musíte pochopit, jak rozložit data do uzlů. Protože když všechno nacpeme do jednoho (mimochodem, může jich být tisíc, dva tisíce, pět – kolik chcete), o distribuci tady vlastně nejde. Proto potřebujeme matematickou funkci, která vrátí číslo. Jen číslo, dlouhý int, který bude spadat do nějakého rozsahu. A budeme mít jeden uzel zodpovědný za jeden rozsah, druhý za druhý, n-tý za n-tý.

Cassandra. Jak nezemřít, když znáte pouze Oracle

Toto číslo je převzato pomocí hashovací funkce, která je aplikována na to, co nazýváme Partition key. Toto je sloupec, který je uveden v direktivě Primary key, a toto je sloupec, který bude prvním a nejzákladnějším klíčem mapy. Určuje, který uzel bude přijímat která data. Tabulka je vytvořena v Cassandře s téměř stejnou syntaxí jako v SQL:

CREATE TABLE users (
	user_id uu id,
	name text,
	year int,
	salary float,
	PRIMARY KEY(user_id)

)

Primární klíč se v tomto případě skládá z jednoho sloupce a je to také rozdělovací klíč.

Jak si povedou naši uživatelé? Některé půjdou do jednoho uzlu, některé do jiného a některé do třetího. Výsledkem je obyčejná hashovací tabulka, známá také jako mapa, známá také jako slovník v Pythonu, nebo jednoduchá struktura Key value, ze které můžeme číst všechny hodnoty, číst a zapisovat podle klíče.

Cassandra. Jak nezemřít, když znáte pouze Oracle

Vyberte: když se povolení filtrování změní na úplné skenování nebo co nedělat

Pojďme napsat nějaké vybrané prohlášení: select * from users where, userid = . Dopadá to jako v Oracle: napíšeme select, specifikujeme podmínky a vše funguje, uživatelé to dostanou. Pokud ale vyberete například uživatele s určitým rokem narození, Cassandra si stěžuje, že nemůže požadavek splnit. Protože neví vůbec nic o tom, jak distribuujeme data o roce narození - má pouze jeden sloupec označený jako klíč. Pak řekne: „Dobře, stále mohu splnit tento požadavek. Přidat povolení filtrování." Přidáme směrnici, vše funguje. A v tuto chvíli se stane něco hrozného.

Když běžíme na testovacích datech, je vše v pořádku. A když spustíte dotaz ve výrobě, kde máme třeba 4 miliony záznamů, tak nám všechno moc nejde. Povolit filtrování je totiž direktiva, která Cassandře umožňuje shromáždit všechna data z této tabulky ze všech uzlů, všech datových center (pokud je jich v tomto clusteru mnoho) a teprve poté je filtrovat. Toto je analogie Full Scan a málokdo z toho má radost.

Pokud bychom potřebovali uživatele pouze podle ID, bylo by to v pořádku. Někdy ale potřebujeme napsat další dotazy a uložit další omezení výběru. Proto si pamatujeme: toto všechno je mapa, která má rozdělovací klíč, ale uvnitř je setříděná mapa.

A má také klíč, kterému říkáme Clustering Key. Tento klíč, který se zase skládá ze sloupců, které vybereme, s jejichž pomocí Cassandra pochopí, jak jsou její data fyzicky tříděna a budou umístěna na každém uzlu. To znamená, že u některého klíče Partition vám klíč Clustering přesně řekne, jak vložit data do tohoto stromu, jaké místo tam zabere.

Jedná se skutečně o strom, jednoduše se tam volá komparátor, kterému předáváme určitou množinu sloupců ve formě objektu a je také specifikován jako seznam sloupců.

CREATE TABLE users_by_year_salary_id (
	user_id uuid,
	name text,
	year int,
	salary float,
	PRIMARY KEY((year), salary, user_id)

Věnujte pozornost direktivě Primární klíč, její první argument (v našem případě rok) je vždy Partition key. Může se skládat z jednoho nebo více sloupců, na tom nezáleží. Pokud existuje několik sloupců, je třeba je znovu odstranit v závorkách, aby jazykový preprocesor pochopil, že toto je primární klíč a za ním jsou všechny ostatní sloupce Clusteringový klíč. V tomto případě budou přenášeny v komparátoru v pořadí, v jakém se objevují. To znamená, že první sloupec je významnější, druhý je méně významný a tak dále. Jak píšeme například pole rovná se pro datové třídy: vypíšeme pole a k nim napíšeme, která jsou větší a která menší. V Cassandře jsou to relativně vzato pole datové třídy, na které se bude vztahovat rovná se pro ni napsaná.

Nastavujeme třídění a zavádíme omezení

Je třeba si uvědomit, že pořadí řazení (sestupně, vzestupně, cokoliv) se nastavuje ve stejném okamžiku, kdy je klíč vytvořen, a nelze jej později změnit. Fyzicky určuje, jak budou data tříděna a jak budou uložena. Pokud potřebujete změnit klíč Clustering nebo pořadí řazení, budete muset vytvořit novou tabulku a přenést do ní data. Toto nebude fungovat se stávajícím.

Cassandra. Jak nezemřít, když znáte pouze Oracle

Naplnili jsme naši tabulku uživateli a viděli jsme, že se dostali do kruhu, nejprve podle roku narození a poté uvnitř každého uzlu podle platu a ID uživatele. Nyní můžeme vybírat zavedením omezení.

Znovu se objeví naše pracovní where, and, a získáme uživatele a vše je opět v pořádku. Pokud se ale pokusíme použít pouze část Clustering key, a to méně významnou, pak si Cassandra bude okamžitě stěžovat, že nemůže najít místo na naší mapě, kde by tento objekt, který má tato pole pro nulový komparátor, a tento to bylo právě nastaveno, - kde leží. Budu muset znovu vytáhnout všechna data z tohoto uzlu a filtrovat je. A toto je analogie úplného skenování v uzlu, to je špatné.

V jakékoli nejasné situaci vytvořte novou tabulku

Pokud chceme být schopni cílit na uživatele podle ID, věku nebo platu, co bychom měli dělat? Nic. Stačí použít dvě tabulky. Pokud potřebujete uživatele oslovit třemi různými způsoby, budou k dispozici tři tabulky. Pryč jsou doby, kdy jsme šetřili místo na šroubu. Toto je nejlevnější zdroj. Stojí mnohem méně než doba odezvy, což může být pro uživatele škodlivé. Pro uživatele je mnohem příjemnější dostat něco za vteřinu než za 10 minut.

Vyměňujeme nepotřebný prostor a denormalizovaná data za schopnost dobře škálovat a spolehlivě fungovat. Ve skutečnosti je totiž cluster, který se skládá ze tří datových center, z nichž každé má pět uzlů, s přijatelnou úrovní uchování dat (když se nic neztratí), schopen přežít smrt jednoho datového centra úplně. A další dva uzly v každém ze zbývajících dvou. A teprve potom začnou problémy. To je docela dobrá redundance, stojí za to pár SSD disků a procesorů navíc. Proto, abyste mohli používat Cassandru, což nikdy není SQL, ve kterém nejsou žádné vztahy, cizí klíče, musíte znát jednoduchá pravidla.

Vše navrhneme dle vašeho požadavku. Hlavní nejsou data, ale to, jak s nimi aplikace bude pracovat. Pokud potřebuje přijímat různá data různými způsoby nebo stejná data různými způsoby, musíme to dát způsobem, který je pro aplikaci vhodný. Jinak v Úplném skenování selžeme a Cassandra nám nedá žádnou výhodu.

Denormalizace dat je normou. Zapomínáme na normální formy, už nemáme relační databáze. Když něco položíme 100x, lehne si to 100x. Pořád je to levnější než zastavit.

Klíče pro rozdělení vybíráme tak, aby byly distribuovány normálně. Nechceme, aby hash našich klíčů spadal do jednoho úzkého rozsahu. To znamená, že rok narození ve výše uvedeném příkladu je špatný příklad. Přesněji řečeno, je dobré, když jsou naši uživatelé normálně rozděleni podle roku narození, a špatné, pokud se bavíme o žácích 5. ročníku – tam to dělení nebude moc dobré.

Třídění je vybráno jednou ve fázi vytváření Clustering Key. Pokud je nutné jej změnit, budeme muset aktualizovat naši tabulku jiným klíčem.

A nejdůležitější věc: pokud potřebujeme získat stejná data 100 různými způsoby, budeme mít 100 různých tabulek.

Zdroj: www.habr.com

Přidat komentář