Cassandra. Paano hindi mamatay kung Oracle lang ang alam mo

Hoy Habr.

Ang pangalan ko ay Misha Butrimov, nais kong sabihin sa iyo ng kaunti tungkol kay Cassandra. Ang aking kwento ay magiging kapaki-pakinabang sa mga hindi pa nakatagpo ng mga database ng NoSQL - mayroon itong maraming mga tampok sa pagpapatupad at mga pitfalls na kailangan mong malaman tungkol sa. At kung wala ka pang nakita maliban sa Oracle o anumang iba pang relational database, ang mga bagay na ito ay magliligtas sa iyong buhay.

Ano bang maganda kay Cassandra? Ito ay isang database ng NoSQL na idinisenyo nang walang isang punto ng pagkabigo na mahusay na sukat. Kung kailangan mong magdagdag ng ilang terabytes para sa ilang database, magdagdag ka lang ng mga node sa ring. Palawakin ito sa isa pang data center? Magdagdag ng mga node sa cluster. Dagdagan ang naprosesong RPS? Magdagdag ng mga node sa cluster. Gumagana din ito sa kabaligtaran na direksyon.

Cassandra. Paano hindi mamatay kung Oracle lang ang alam mo

Ano pa ang magaling niya? Ito ay tungkol sa paghawak ng maraming kahilingan. Ngunit magkano ang marami? 10, 20, 30, 40 libong mga kahilingan sa bawat segundo ay hindi gaanong. 100 libong mga kahilingan sa bawat segundo para sa pag-record - masyadong. May mga kumpanya na nagsabing nagtatago sila ng 2 milyong kahilingan kada segundo. Malamang kailangan nilang maniwala.

At sa prinsipyo, si Cassandra ay may isang malaking pagkakaiba mula sa relational data - hindi ito katulad sa kanila. At ito ay napakahalagang tandaan.

Hindi lahat ng mukhang pareho ay gumagana

Minsan ang isang kasamahan ay lumapit sa akin at nagtanong: "Narito ang isang CQL Cassandra query language, at mayroon itong isang piling pahayag, mayroon itong kung saan, mayroon at. Sumulat ako ng mga liham at hindi ito gumagana. Bakit?". Ang pagtrato kay Cassandra na parang relational database ay ang perpektong paraan para magpakamatay nang marahas. At hindi ko ito pino-promote, ito ay ipinagbabawal sa Russia. Magde-design ka lang ng mali.

Halimbawa, may customer na lumapit sa amin at nagsabing: “Bumuo tayo ng database para sa mga serye sa TV, o database para sa direktoryo ng recipe. Magkakaroon kami ng mga food dishes doon o isang listahan ng mga serye sa TV at mga artista sa loob nito." Masaya naming sinasabi: "Tayo na!" Magpadala lamang ng dalawang byte, isang pares ng mga palatandaan at tapos ka na, ang lahat ay gagana nang napakabilis at mapagkakatiwalaan. At lahat ay maayos hanggang sa dumating ang mga customer at sabihin na ang mga maybahay ay nilulutas din ang kabaligtaran na problema: mayroon silang listahan ng mga produkto, at nais nilang malaman kung anong ulam ang gusto nilang lutuin. Patay ka.

Ito ay dahil ang Cassandra ay isang hybrid na database: sabay-sabay itong nagbibigay ng mahalagang halaga at nag-iimbak ng data sa malalawak na column. Sa Java o Kotlin, maaari itong ilarawan tulad nito:

Map<RowKey, SortedMap<ColumnKey, ColumnValue>>

Ibig sabihin, isang mapa na naglalaman din ng pinagsunod-sunod na mapa. Ang unang susi sa mapang ito ay ang Row key o Partition key - ang partitioning key. Ang pangalawang key, na siyang susi sa isang nakaayos nang mapa, ay ang Clustering key.

Upang ilarawan ang pamamahagi ng database, gumuhit tayo ng tatlong node. Ngayon ay kailangan mong maunawaan kung paano i-decompose ang data sa mga node. Dahil kung i-cram natin ang lahat sa isa (nga pala, maaaring isang libo, dalawang libo, lima - kung gaano karami ang gusto mo), hindi talaga ito tungkol sa pamamahagi. Samakatuwid, kailangan namin ng isang mathematical function na magbabalik ng isang numero. Isang numero lang, isang mahabang int na mahuhulog sa ilang hanay. At magkakaroon tayo ng isang node na responsable para sa isang saklaw, ang pangalawa para sa pangalawa, ang ika-XNUMX para sa ika-XNUMX.

Cassandra. Paano hindi mamatay kung Oracle lang ang alam mo

Kinukuha ang numerong ito gamit ang hash function, na inilalapat sa tinatawag nating Partition key. Ito ang column na tinukoy sa Primary key directive, at ito ang column na magiging una at pinakapangunahing key ng mapa. Tinutukoy nito kung aling node ang tatanggap ng data. Ang isang talahanayan ay nilikha sa Cassandra na may halos parehong syntax tulad ng sa SQL:

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

)

Ang Primary key sa kasong ito ay binubuo ng isang column, at ito rin ang partitioning key.

Paano gaganap ang aming mga gumagamit? Ang ilan ay mapupunta sa isang node, ang ilan sa isa pa, at ang ilan sa isang ikatlo. Ang resulta ay isang ordinaryong hash table, na kilala rin bilang isang mapa, na kilala rin bilang isang diksyunaryo sa Python, o isang simpleng Key value structure kung saan maaari nating basahin ang lahat ng value, basahin at isulat sa pamamagitan ng key.

Cassandra. Paano hindi mamatay kung Oracle lang ang alam mo

Piliin: kapag ang payagan ang pag-filter ay naging ganap na pag-scan, o kung ano ang hindi dapat gawin

Sumulat tayo ng ilang piling pahayag: select * from users where, userid = . Ito ay lumalabas tulad ng sa Oracle: sumulat kami ng piliin, tukuyin ang mga kondisyon at lahat ay gumagana, nakukuha ito ng mga gumagamit. Ngunit kung pipiliin mo, halimbawa, ang isang user na may partikular na taon ng kapanganakan, nagrereklamo si Cassandra na hindi nito matutupad ang kahilingan. Dahil wala siyang alam sa lahat tungkol sa kung paano kami namamahagi ng data tungkol sa taon ng kapanganakan - mayroon lang siyang isang column na nakasaad bilang isang susi. Then she says, “Okay, kaya ko pa namang tuparin ang request na ito. Magdagdag ng allow filtering." Idinagdag namin ang direktiba, gumagana ang lahat. At sa sandaling ito ay may nangyaring kakila-kilabot.

Kapag tumakbo kami sa data ng pagsubok, maayos ang lahat. At kapag nagsagawa ka ng isang query sa produksyon, kung saan mayroon kaming, halimbawa, 4 na milyong mga tala, kung gayon ang lahat ay hindi masyadong maganda para sa amin. Dahil ang allow filtering ay isang direktiba na nagbibigay-daan kay Cassandra na kolektahin ang lahat ng data mula sa talahanayang ito mula sa lahat ng node, lahat ng data center (kung marami sa kanila ang nasa cluster na ito), at pagkatapos ay i-filter lang ito. Ito ay isang analogue ng Full Scan, at halos walang natutuwa dito.

Kung kailangan lang namin ng mga user sa pamamagitan ng ID, ayos lang kami dito. Ngunit kung minsan kailangan nating magsulat ng iba pang mga query at magpataw ng iba pang mga paghihigpit sa pagpili. Samakatuwid, tandaan namin: lahat ito ay isang mapa na may partitioning key, ngunit sa loob nito ay isang pinagsunod-sunod na mapa.

At mayroon din siyang susi, na tinatawag naming Clustering Key. Ang key na ito, na, naman, ay binubuo ng mga column na pipiliin namin, sa tulong ng kung saan nauunawaan ni Cassandra kung paano pisikal na pinagbubukod-bukod ang data nito at matatagpuan sa bawat node. Iyon ay, para sa ilang Partition key, eksaktong sasabihin sa iyo ng Clustering key kung paano itulak ang data sa punong ito, kung saang lugar ito dadalhin doon.

Ito ay talagang isang puno, ang isang comparator ay simpleng tinatawag doon, kung saan ipinapasa namin ang isang tiyak na hanay ng mga haligi sa anyo ng isang bagay, at ito ay tinukoy din bilang isang listahan ng mga haligi.

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

Bigyang-pansin ang direktiba ng Pangunahing key; ang unang argumento nito (sa aming kaso, ang taon) ay palaging Partition key. Maaari itong binubuo ng isa o higit pang mga column, hindi mahalaga. Kung mayroong ilang column, kailangan itong tanggalin muli sa mga bracket upang maunawaan ng preprocessor ng wika na ito ang Pangunahing key, at sa likod nito ang lahat ng iba pang column ay ang Clustering key. Sa kasong ito, ipapadala ang mga ito sa comparator sa pagkakasunud-sunod ng paglitaw ng mga ito. Iyon ay, ang unang hanay ay mas makabuluhan, ang pangalawa ay hindi gaanong makabuluhan, at iba pa. Kung paano kami sumulat, halimbawa, ay katumbas ng mga patlang para sa mga klase ng data: inilista namin ang mga patlang, at para sa kanila isinusulat namin kung alin ang mas malaki at alin ang mas maliit. Sa Cassandra, ito ay, medyo nagsasalita, ang mga patlang ng klase ng data, kung saan ilalapat ang mga katumbas na nakasulat para dito.

Nagtakda kami ng pag-uuri at nagpapataw ng mga paghihigpit

Kailangan mong tandaan na ang pagkakasunud-sunod ng pag-uuri (pababa, pataas, anuman) ay nakatakda sa parehong sandali kapag ginawa ang susi, at hindi na ito mababago sa ibang pagkakataon. Pisikal nitong tinutukoy kung paano pag-uuri-uriin ang data at kung paano ito iimbak. Kung kailangan mong baguhin ang Clustering key o sort order, kakailanganin mong gumawa ng bagong table at maglipat ng data dito. Hindi ito gagana sa isang umiiral na.

Cassandra. Paano hindi mamatay kung Oracle lang ang alam mo

Pinuno namin ang aming talahanayan ng mga user at nakita namin na nahulog sila sa isang singsing, una sa pamamagitan ng taon ng kapanganakan, at pagkatapos ay sa loob ng bawat node sa pamamagitan ng suweldo at user ID. Ngayon ay maaari na tayong pumili sa pamamagitan ng pagpapataw ng mga paghihigpit.

Lumilitaw muli ang aming nagtatrabaho where, and, at nakakakuha kami ng mga user, at maayos na muli ang lahat. Ngunit kung susubukan naming gumamit lamang ng isang bahagi ng Clustering key, at isang hindi gaanong makabuluhan, pagkatapos ay agad na magrereklamo si Cassandra na hindi nito mahanap ang lugar sa aming mapa kung saan ang bagay na ito, na mayroong mga field na ito para sa null comparator, at ang isang ito. itinakda lang iyon, - kung saan siya nakahiga. Kailangan kong hilahin muli ang lahat ng data mula sa node na ito at i-filter ito. At ito ay isang analogue ng Full Scan sa loob ng isang node, ito ay masama.

Sa anumang hindi malinaw na sitwasyon, lumikha ng bagong talahanayan

Kung gusto nating ma-target ang mga user ayon sa ID, o ayon sa edad, o sa suweldo, ano ang dapat nating gawin? Wala. Gumamit lamang ng dalawang mesa. Kung kailangan mong abutin ang mga user sa tatlong magkakaibang paraan, magkakaroon ng tatlong talahanayan. Lumipas na ang mga araw na nakatipid kami ng espasyo sa turnilyo. Ito ang pinakamurang mapagkukunan. Mas mura ito kaysa sa oras ng pagtugon, na maaaring makasama sa user. Ito ay mas kaaya-aya para sa gumagamit na makatanggap ng isang bagay sa isang segundo kaysa sa 10 minuto.

Ipinagpalit namin ang hindi kinakailangang espasyo at denormalized na data para sa kakayahang mag-scale nang maayos at gumana nang mapagkakatiwalaan. Pagkatapos ng lahat, sa katunayan, ang isang kumpol na binubuo ng tatlong data center, bawat isa ay may limang node, na may katanggap-tanggap na antas ng pag-iingat ng data (kapag walang nawala), ay kayang mabuhay nang buo sa pagkamatay ng isang data center. At dalawa pang node sa bawat isa sa natitirang dalawa. At pagkatapos lamang nito magsisimula ang mga problema. Ito ay isang magandang redundancy, ito ay nagkakahalaga ng ilang dagdag na SSD drive at processor. Samakatuwid, upang magamit ang Cassandra, na hindi kailanman SQL, kung saan walang mga relasyon, mga dayuhang susi, kailangan mong malaman ang mga simpleng patakaran.

Idinisenyo namin ang lahat ayon sa iyong kahilingan. Ang pangunahing bagay ay hindi ang data, ngunit kung paano gagana ang application dito. Kung kailangan nitong makatanggap ng iba't ibang data sa iba't ibang paraan o sa parehong data sa iba't ibang paraan, dapat nating ilagay ito sa paraang maginhawa para sa aplikasyon. Kung hindi, mabibigo tayo sa Full Scan at hindi tayo bibigyan ni Cassandra ng anumang kalamangan.

Ang denormalizing data ay ang pamantayan. Nakalimutan namin ang tungkol sa mga normal na form, wala na kaming relational database. Kung ibababa natin ng 100 beses ang isang bagay, hihiga ito ng 100 beses. Mas mura pa ito kaysa huminto.

Pinipili namin ang mga susi para sa paghahati upang ang mga ito ay maipamahagi nang normal. Hindi namin gustong mahulog ang hash ng aming mga susi sa isang makitid na hanay. Iyon ay, ang taon ng kapanganakan sa halimbawa sa itaas ay isang masamang halimbawa. Mas tiyak, ito ay mabuti kung ang aming mga gumagamit ay karaniwang ipinamamahagi ayon sa taon ng kapanganakan, at masama kung ang pag-uusapan natin ay tungkol sa mga mag-aaral sa ika-5 baitang - ang paghahati doon ay hindi magiging napakahusay.

Pinipili ang pag-uuri nang isang beses sa yugto ng paggawa ng Clustering Key. Kung kailangan itong baguhin, kailangan naming i-update ang aming talahanayan gamit ang ibang key.

At ang pinakamahalagang bagay: kung kailangan nating kunin ang parehong data sa 100 magkakaibang paraan, magkakaroon tayo ng 100 magkakaibang talahanayan.

Pinagmulan: www.habr.com

Magdagdag ng komento