2.1 Carane shard lan alon mudhun N kaping?
Sampeyan bisa shard lan alon mudhun persis N kaping kaya iki:
- Kirimi panjalukan docs00...docs15 kanthi urut , ora sejajar.
- Ing pitakonan prasaja, nggawe pilihan ora dening tombol , WHERE soko=234.
Ing kasus iki, bagean serialized (serial) njupuk ora 1% lan ora 5%, nanging bab 20% ing database modern. Sampeyan uga bisa njaluk 50% saka bagean serialized yen sampeyan ngakses database nggunakake protokol binar wildly efisien utawa link minangka perpustakaan dinamis menyang script Python.
Sisa wektu pangolahan panjalukan sing prasaja bakal dikuwasani dening operasi non-parallelisable saka parsing panjalukan, nyiapake rencana, etc. Sing, ora maca rekaman slows mudhun.
Yen kita mbagi data dadi 16 tabel lan mlaku kanthi urutan, kaya biasane ing basa pemrograman PHP, umpamane, (ora apik banget nalika ngluncurake proses asinkron), mula kita bakal entuk slowdown 16 kali. Lan, mbok menawa, malah luwih, amarga jaringan round-trip uga bakal ditambahake.
Dumadakan, pilihan basa pamrograman penting nalika sharding.
Elinga babagan pilihan basa pamrograman, amarga yen sampeyan ngirim pitakon menyang database (utawa server telusuran) kanthi urutan, banjur saka endi akselerasi kasebut? Nanging, bakal ana slowdown.
2.2 Babagan semi-otomatis
Ing panggonan-panggonan, kecanggihan teknologi informasi menehi inspirasi horor chthonic. Contone, MySQL out of the box ora duwe implementasi sharding kanggo versi tartamtu, nanging ukuran database sing digunakake ing perang tuwuh dadi nilai sing ora sopan.
Kasangsaran manungsa nalika ngadhepi DBA individu wis disiksa nganti pirang-pirang taun lan nulis sawetara solusi sharding sing ala adhedhasar apa-apa. Sawisé iku, siji luwih utawa kurang prayoga solusi sharding ditulis disebut ProxySQL (MariaDB/Spider, PG/pg_shard/Citus, ...). Iki minangka conto sing kondhang saka blotch iki.
ProxySQL minangka sakabehe, mesthi, solusi kelas perusahaan lengkap kanggo open source, kanggo nuntun lan liya-liyane. Nanging salah sawijining tugas sing kudu ditanggulangi yaiku sharding kanggo database, sing ora bisa dipecah kanthi cara manungsa. Sampeyan ndeleng, ora ana switch "shards = 16", sampeyan kudu nulis ulang saben request ing aplikasi, lan ana akeh ing panggonan, utawa sijine sawetara lapisan penengah antarane aplikasi lan database sing katon: "Hmm ... PILIH * FROM dokumen? Ya, iku kudu bejat menyang 16 cilik SELECT * FROM server1.document1, SELECT * FROM server2.document2 - kanggo server iki karo login / sandi kuwi, siji iki karo liyane. Yen ana sing ora mangsuli, banjur ... ", lsp. Persis iki bisa ditindakake kanthi blotches penengah. Padha rada kurang saka kabeh database. Kanggo PostgreSQL, aku ngerti,
Konfigurasi saben tembelan tartamtu minangka topik raksasa sing kapisah sing ora cocog karo siji laporan, mula kita mung bakal ngrembug konsep dhasar. Ayo kita ngomong sethithik babagan teori buzz.
2.3 Automasi sing sampurna?
Kabèh téori njupuk dhuwur ing kasus sharding ing huruf iki F () , prinsip dhasar tansah padha kira-kira: shard_id = F (obyek).
Sharding - apa iku kabeh? Kita duwe 2 milyar cathetan (utawa 64). Kita arep kanggo break mau menyang sawetara bêsik. Pitakonan sing ora dikarepke muncul - kepiye? Miturut prinsip apa aku kudu nyebar 2 milyar cathetan (utawa 64) ing 16 server kasedhiya kanggo kula?
Matématikawan laten ing kita kudu suggest sing ing pungkasan tansah ana sawetara fungsi gaib sing, kanggo saben document (obyek, baris, etc.), bakal nemtokake kang Piece kanggo sijine iku.
Luwih jero menyang matématika, fungsi iki tansah gumantung ora mung ing obyek kasebut (baris dhewe), nanging uga ing setelan eksternal kayata jumlah total pecahan. A fungsi sing kanggo saben obyek kudu ngomong ngendi kanggo nyelehake, ora bisa bali Nilai luwih saka ana server ing sistem. Lan fungsi sing rada beda:
shard_func = F1(object);
shard_id = F2(shard_func, ...);
shard_id = F2(F1(object), current_num_shards, ...).
Nanging luwih kita ora bakal dig menyang wilds iki fungsi individu, kita mung bakal pirembagan bab apa fungsi Piandel F ().
2.4 Apa F()?
Padha bisa teka munggah karo akeh beda lan akeh mekanisme implementasine beda. Ringkesan conto:
- F = rand() % nums_shards
- F = somehash(object.id) % num_shards
- F = object.date % num_shards
- F = object.user_id % num_shards
- ...
- F = shard_table [ somehash() |… object.date |… ]
Kasunyatan sing menarik - sampeyan bisa kanthi alami nyebarake kabeh data kanthi acak - kita mbuwang rekaman sabanjure ing server sing sewenang-wenang, ing inti sing sewenang-wenang, ing tabel sing sewenang-wenang. Ora bakal ana rasa seneng, nanging bakal bisa.
Ana cara sing rada luwih cerdas kanggo shard kanthi fungsi hash sing bisa direproduksi utawa malah konsisten, utawa shard dening sawetara atribut. Ayo dadi liwat saben cara.
F = rand()
Panyebaran dudu cara sing bener. Siji masalah: kita nyebar 2 milyar rekaman ing sewu server kanthi acak, lan kita ora ngerti ngendi rekaman kasebut. Kita kudu narik metu user_1, nanging kita ora ngerti ngendi iku. Kita menyang sewu server lan ngurutake kabeh - piye wae iki ora efisien.
F = suket()
Ayo nyebarake pangguna kanthi cara diwasa: ngitung fungsi hash sing bisa direproduksi saka user_id, njupuk sisa divisi kanthi jumlah server, lan langsung hubungi server sing dikarepake.
Yagene kita nindakake iki? Lan banjur, sing kita duwe highload lan boten liya mathuk menyang siji server. Yen pas, urip bakal dadi prasaja.
Apik banget, kahanan wis apik, supaya entuk siji rekaman, kita menyang server sing dikenal luwih dhisik. Nanging yen kita duwe sawetara kunci, banjur ing kabeh kisaran iki, kita kudu ngliwati kabeh nilai tombol lan, ing watesan, pindhah menyang pirang-pirang pecahan kaya sing kita duwe kunci ing kisaran, utawa malah saben server. Kahanan wis apik, mesthi, nanging ora kanggo kabeh panjalukan. Sawetara pitakon wis kena pengaruh.
Sharding alami (F = object.date % num_shards)
Kadhangkala, yaiku, asring, 95% lalu lintas lan 95% muatan minangka panjaluk sing duwe sawetara jinis sharding alami. Contone, 95% pitakon sosial-analitik kanthi kondisional mengaruhi data mung sajrone 1 dina, 3 dina, 7 dina, lan 5% liyane nuduhake sawetara taun kepungkur. Nanging 95% panjalukan kanthi alami dibuwang miturut tanggal, kapentingan pangguna sistem fokus ing sawetara dina pungkasan.
Ing kasus iki, sampeyan bisa dibagi data miturut tanggal, contone, siji dina, lan tindakake respon kanggo panjalukan kanggo laporan kanggo sawetara dina utawa obyek saka dina iki kanggo shard iki lan pindhah.
Urip saya apik - saiki ora mung ngerti lokasi obyek tartamtu, nanging uga ngerti babagan jarak kasebut. Yen kita dijaluk ora kanggo sawetara tanggal, nanging kanggo sawetara kolom liyane, banjur, mesthi, kita kudu ngliwati kabeh shards. Nanging miturut aturan game, mung 5% saka panjalukan kasebut.
Kayane kita wis nemokake solusi sing cocog kanggo kabeh, nanging ana rong masalah:
- Solusi iki dicocogake kanggo kasus tartamtu, nalika 95% panjalukan mung melu minggu kepungkur.
- Wiwit 95% panjalukan ndemek minggu kepungkur, kabeh bakal tiba ing siji beling sing dilayani minggu kepungkur. Shard iki bakal nyawiji, dene kabeh liyane bakal nganggur sajrone wektu iki. Ing wektu sing padha, sampeyan ora bisa mbuwang, data arsip uga kudu disimpen.
Ora ujar manawa iki minangka skema sharding sing ala - kita ngilangi data panas, nanging ana sing kudu ditindakake kanthi shard sing paling panas.
Masalah iki ditanggulangi dening antics, mlumpat lan poultices, sing, Tambah ing jumlah replika kanggo kobong dina saiki, banjur ngurangi bertahap ing jumlah replika nalika dina iki dadi kepungkur lan pindhah menyang arsip. Ora ana solusi becik sing diarani "sampeyan mung kudu nyebar data ing kluster kanthi fungsi hash sihir kanthi cara sing salah".
2.5 Rega sing kudu dibayar
Secara resmi, saiki kita ngerti "kabeh". Bener, kita ora ngerti siji sirah raksasa lan loro sirah sing luwih cilik.
1. Lara prasaja: diolesi banget
Iki minangka conto saka buku teks, sing meh ora ana ing perang, nanging dumadakan.
- Minangka conto karo tanggal, mung tanpa tanggal!
- Distribusi ora rata (bisa ditemokake) sing ora disengaja .
Dheweke milih mekanisme sharding, lan / utawa data diganti, lan, mesthi, PM ora ngirim syarat (kita ora duwe kesalahan ing kode, PM tansah ora laporan syarat), lan distribusi dadi monstroously ora rata. Sing, padha ora kejawab kritéria.
Kanggo nyekel, sampeyan kudu ndeleng ukuran shards. Temtunipun kita bakal weruh masalah ing wayahe nalika salah siji shards kita overheat utawa dadi 100 kaping luwih gedhe tinimbang liyane. Sampeyan bisa ndandani iku mung kanthi ngganti tombol utawa fungsi sharding.
Iki masalah prasaja, jujur, Aku ora mikir sing paling siji saka satus bakal mbukak ing urip iki, nanging dumadakan bakal bantuan ing paling wong.
2. "Invincible" pain: aggregation, gabung
Kepiye carane nggawe pilihan sing nggabungake milyar cathetan saka siji meja kanggo milyar cathetan saka meja liyane?- Carane "cepet" ngetung ... Endi randcol ANTARA aaa LAN bbb?
- Carane "pinter" nindakake ... users_32shards JOIN posts_1024 shards?
Jawaban singkat: ora, nandhang sangsara!
Yen sampeyan mbagekke milyar cathetan kanggo sewu server ing tabel pisanan supaya padha bisa luwih cepet, lan padha ing meja kapindho, banjur alamiah sewu kanggo sewu server kudu diajak saben liyane ing pasangan. A yuta sambungan ora bakal bisa uga. Yen kita nggawe panjalukan kanggo database (search, panyimpenan, nyimpen dokumen utawa sistem file mbagekke) sing ora pas uga karo sharding, panjalukan iki bakal alon mudhun wildly.
Titik penting yaiku sawetara panjaluk mesthi ora kasil diolesi lan bakal alon . Penting kanggo nyoba kanggo nyilikake persentasi. Akibaté, ora perlu nggawe gabungan raksasa kanthi rekor milyar nganti milyar. Yen bisa kanggo niru meja cilik, relatif sing sampeyan gabung ing meja bareng raksasa, kanggo kabeh kelenjar, sampeyan kudu nindakake. Yen gabungan kasebut bener-bener lokal ing sawetara cara, contone, sampeyan bisa nyelehake pangguna lan kiriman kanthi sisih, beling kanthi cara sing padha, lan nindakake kabeh gabungan ing mesin sing padha - sampeyan mung kudu nglakoni. .
Iki minangka kursus kuliah sing kapisah sajrone telung dina, mula ayo pindhah menyang nyeri neraka pungkasan lan algoritma sing beda kanggo ngatasi.
2.6. Nyeri Komplek/Dawa: Resharding
Siapke: yen sampeyan ngethok data kaping pisanan ing urip sampeyan, rata-rata sampeyan bakal ngrusak data kaping lima maneh.
Ora ketompo carane akeh klompok sampeyan ngatur, sampeyan isih kudu reshard.
Yen sampeyan banget pinter lan begja, banjur overshard ing paling sapisan. Nanging yen sampeyan yakin, amarga nalika sampeyan mikir yen 10 unit cukup kanggo pangguna, ana wong ing wektu kasebut nulis panjaluk 30, lan rencana njaluk 100 unit sumber daya sing ora dingerteni. Shards ora tau cukup. Kanthi skema sharding pisanan, ing kasus apa wae, sampeyan bakal kantun - sampeyan mesthi kudu nambah jumlah server sing bakal ditambahake, utawa nindakake tindakan liya - umume, piye wae ngemas ulang data kasebut.
Iku apik yen kita duwe kakuwasan becik saka loro: ana 16 pecahan server, saiki 32. Iku luwih nyenengake yen ana 17, iku 23 - loro nomer vasimally prima. Kepiye database nindakake, bisa uga ana sihir ing njero?
Jawaban sing bener yaiku: ora, ora ana sihir ing njero, dheweke duwe neraka.
Sabanjure, kita bakal nimbang apa sing bisa ditindakake "kanthi tangan", mbok menawa kita bakal ngerti "minangka mesin otomatis".
Ing bathuk #1. Pindhah Kabeh
Kanggo kabeh obyek, kita nimbang NewF (obyek), pindhah menyang shard anyar.
Kasempatan NewF () = OldF () cocog kurang.
Ayo kita nutupi meh kabeh.
Oh.
Muga-muga ora ana neraka sing bisa nransfer kabeh 2 milyar cathetan saka pecahan lawas menyang sing anyar. Pendekatan naif bisa dingerteni: ana 17 mesin, 6 mesin ditambahake ing kluster, 2 milyar cathetan diurutake, dipindhah saka 17 mesin dadi 23 mesin. Sawise saben 10 taun, sampeyan bisa uga bisa nindakake. Nanging sakabèhé iku tumindak ala.
Ing bathuk #2. Pindhah setengah
Dandan sabanjure naif - ayo ninggalake skema bodho kasebut - bakal nglarang 17 mobil saka resharding dadi 23, lan kita bakal tansah reshard 16 mobil dadi 32 mobil! Banjur, miturut teori, kita kudu mindhah persis setengah saka data, lan ing laku kita uga bisa nindakake iki.
Kanggo kabeh obyek, kita nimbang NewF (obyek), pindhah menyang shard anyar.
Dulu 2^N, saiki dadi 2^(N+1) pecahan.
Kemungkinan cocog NewF () = OldF () iku 0,5.
Ayo transfer babagan 50% data.
Optimal, nanging mung dianggo kanggo kakuwasan loro.
Ing asas, kabeh iku nggoleki, kajaba kanggo naleni daya loro ing syarat-syarat nomer mobil. Pendekatan naif iki, cukup aneh, bisa ditindakake.
Elinga yen pamisah tambahan kluster kanthi kekuwatan loro ing kasus iki uga optimal. Ing kasus apa wae, nambah 16 mesin menyang kluster 16, kita kudu mindhah setengah saka data - persis setengah lan shift.
Oke, nanging manungsa pancene ora nemokke apa-apa - pitakonan muncul saka pikiran sing kepengin weruh.
Luwih seneng #3. Hashing sing konsisten
Mesthi, gambar kanthi bunder babagan hashing sing konsisten dibutuhake ing kene.
Yen sampeyan google "hashing konsisten", banjur bunder mesthi bakal metu, kabeh asil diisi karo bunderan.
Ide: ayo nggambar pengenal shard (hashes) ing bunder, lan tandhani pengenal server sing di-hash ing ndhuwur. Nalika sampeyan kudu nambah server, kita sijine titik anyar ing bunder, lan apa sing dadi cedhak (lan mung sing dadi cedhak), kita pindhah.
Nalika nambah shard: kita katon liwat ora kabeh, nanging mung 2 "tanggane", kita ngalih ing rata-rata 1 / n.
Nalika mbusak shard: kita mung katon ing shard sing dibusak, kita mung ngalih. Jinis optimal.
Banget efektif ing syarat-syarat nyilikake lalu lintas nalika nambah shard, lan pancen njijiki ing syarat-syarat wawas data normal. Amarga nalika kita hash kabeh obyek iki sing kita disebaraké kanggo nomer akeh mesin, kita nindakake iku relatif unevenly: TCTerms sak bunder sing unevenly spasi, lan mbukak saben simpul tartamtu bisa beda banget saka liyane.
Masalah iki ditanggulangi dening baris pungkasan saka simpul virtual. Saben simpul, saben server ing bunder dituduhake kanthi luwih saka siji titik. Kanthi nambahake server, shard, lan liya-liyane, kita nambah sawetara poin. Saben-saben kita mbusak soko, kita kudu mbusak sawetara TCTerms lan mindhah bagean cilik saka data.
Aku ngomong babagan papan iki kanthi bunder, amarga, contone, skema kasebut ana ing Cassandra. Yaiku, nalika dheweke miwiti nguber cathetan ing antarane simpul, ngerti yen bunder kasebut ndeleng sampeyan lan bisa uga ora setuju.
Nanging, dibandhingake karo cara pisanan, urip wis apik - nalika nambah / mbusak shard, kita wis katon liwat ora kabeh cathetan, nanging mung bagean, lan shift mung bagean.
Manungsa waé, pitakonan iki: apa bisa luwih apik? Lan uga nambah keseragaman loading shards? Padha ngomong iku bisa!
Luwih seneng #4. Rendezvous / HRW
Ide prasaja sabanjure (materi kasebut minangka pendidikan, mula ora ana sing rumit): shard_id = arg max hash(object_id, shard_id).
Napa diarani Rendezvous hashing aku ora ngerti, nanging aku ngerti kok diarani Bobot Random Paling Tinggi. Gampang banget kanggo nggambarake kaya iki:
Kita duwe, contone, 16 shards. Kanggo saben obyek (string) sing kudu dilebokake ing endi wae, kita ngetung 16 hash gumantung saka obyek saka nomer shard. Sapa sing duwe nilai hash paling dhuwur sing menang.
Iki sing diarani HRW-hashing, alias Rendezvous hashing. Bisu minangka kelet, skema kanggo ngitung jumlah shard, pisanan, luwih gampang ing mripat tinimbang bunderan lan menehi beban seragam, ing sisih liya.
Mung negatif iku nambah shard anyar wis worsened kanggo kita. Ana risiko yen nalika nambah shard anyar, kita isih duwe sawetara hash sing bakal diganti lan bisa uga kudu dideleng kabeh. Teknologi mbusak beling ora owah akeh.
Masalah liyane yaiku bobot komputasi kanthi jumlah pecahan sing akeh.
Luwih seneng #5. Techniques liyane
Sing nggumunake, riset ora mandheg lan Google nerbitake sawetara teknologi ruang angkasa anyar saben taun:
- Langsung Hash - Google '2014.
- Multi Probe—Google '2015.
- Maglev-Google '2016.
Yen sampeyan kasengsem ing subyek, sampeyan bisa maca akeh disertasi. Aku saiki data iki kanggo nggawe cetha yen masalah durung ditanggulangi, ora ana super-solusi sing bisa dileksanakake ing kabeh database. Nganti saiki, wong mbela disertasi.
kesimpulan
Ana teknik dhasar penting sing diarani sharding sing dijenengi sawise Gallius Julius Caesar: "Dibagi lan aturan, aturan lan dibagi!". Yen data ora pas menyang siji server, iku perlu kanggo dibagi dadi 20 server.
Sawise sinau kabeh iki, siji kudu entuk kesan yen luwih becik ora ngrusak. Yen sampeyan mutusake manawa luwih becik ora ngrusak, iki minangka perasaan sing bener. Yen sampeyan bisa nambah memori kanggo server $ 100 lan ora shard apa, sampeyan kudu nindakake. Nalika sharding, sistem mbagekke Komplek bakal katon karo nransfer data bali lan kasebut, numpuk data ing ora ana kang ngerti ngendi. Yen bisa nyingkiri, kudu dihindari.
Luwih becik ora nindakake kanthi tangan, luwih becik yen "dasar" (telusuran, DFS, ...) bisa digoleki dhewe. Ing kasus apa wae, cepet utawa mengko, highload bakal teka lan piye wae data kasebut kudu dibagi. Iku ora kasunyatan sing malah yen basa bisa nindakake dhewe, sampeyan ora bakal nemoni masalah. Elingi babagan fundamentalisme algoritmik - sampeyan kudu ngerti cara kerjane kabeh.
Nalika nyetel sharding pisanan, pilih F () kasebut kanthi teliti, mikir panjalukan, jaringan, etc. Nanging siyap, sampeyan bisa uga kudu milih kaping 2 lan paling ora sapisan sampeyan kudu nindakake kabeh.