Előre haladva ugyanezt az algoritmust alkalmazhatjuk. Mégis, egy kulcsot egy csomóponthoz rendelnénk, függetlenül attól, hogy milyen virtuális csomóponttal találkozott.
Éppen ebben a példában az eloszlás most a következő lenne:
-
N0
: 33,3%
-
N1
: 25%
-
N2
: 41,6%
Minél több virtuális csomópontot határozunk meg csomópontonként, annál inkább egyenletesnek kell lennie az eloszlásnak. Átlagosan, kiszolgálónként 100 virtuális csomópont esetén az egyenletes eloszlás körülbelül 10%. 1000-nél ez körülbelül 3,2%.
Ez a mechanizmus akkor is hasznos, ha különböző méretű csomópontjaink vannak. Ha például egy csomópontot úgy konfigurálunk, hogy elméletileg kétszer akkora terhelést tudjon kezelni, mint a többi, akkor kétszer annyi virtuális csomópontot pörgethetünk fel.
A virtuális csomópontok fő hátránya azonban a memóriaterület. Ha több ezer szervert kellene kezelnünk, akkor ez megabájtnyi memóriát igényelne.
Mielőtt továbblépnénk, érdekes megjegyezni, hogy néha egy algoritmus lényegesen javítható egy kis rész megváltoztatásával. Ez a helyzet például a Google által 2017-ben közzétett, konzisztens hashelés korlátos terheléssel nevű algoritmus esetében. Ez a változat ugyanarra a gyűrűs ötletre épül, amit mi is leírtunk. Mégis, az ő megközelítésük az, hogy minden frissítés (új kulcs vagy csomópont hozzáadása/törlése) esetén egy kis újrakiegyenlítést hajtanak végre. Ez a változat a szórás tekintetében felülmúlja az eredetit, a legrosszabb időbonyolultsággal járó kompromisszummal.
Jump Consistent Hash
2007-ben a Google két mérnöke publikálta a jump consistent hash-et. A gyűrű alapú algoritmushoz képest ez a megvalósítás “nem igényel tárolást, gyorsabb, és jobb munkát végez a kulcstér egyenletes elosztásában a vödrök között, valamint a munkaterhelés egyenletes elosztásában, amikor a vödrök száma változik”. Másképp fogalmazva, javítja a munkaterhelés elosztását a csomópontok között (egy bucket ugyanaz a fogalom, mint egy csomópont) memóriaterhelés nélkül.
Itt az algoritmus C++ nyelven (7 sornyi kód 🤯):
A gyűrűs konzisztens hash esetén 1000 virtuális csomóponttal a standard eltérés körülbelül 3,2% volt. Az ugráskonzisztens hash-ban már nincs szükségünk a virtuális csomópontok fogalmára. Ennek ellenére a standard eltérés továbbra is kevesebb, mint 0,0000001%.
Egy korlátozás azonban van. A csomópontokat sorszámozni kell. Ha van egy listánk a foo
, bar
és baz
szerverekből, akkor nem tudjuk például a bar
-öt eltávolítani. Mégis, ha beállítunk egy adattárolót, akkor alkalmazhatjuk az algoritmust, hogy a shard indexet a shardok teljes száma alapján kapjuk meg. Ezért a jump consistent hash hasznos lehet a shardinggal összefüggésben, de a terheléselosztással nem.
Mi a Perfect Consistent Hashing algoritmus?
Mivel már van némi tapasztalatunk a konzisztens hasheléssel kapcsolatban, lépjünk egy kicsit hátrébb, és nézzük meg, mi lenne a tökéletes algoritmus:
- A kulcsoknak átlagosan csak 1/n százalékát kellene átképezni, ahol n a csomópontok száma.
- O(n) térbonyolultságú, ahol n a csomópontok száma.
- A O(1) időbonyolultság egy csomópont beszúrásakor/eltávolításakor és egy kulcskereséskor.
- Minimális szórás annak biztosítására, hogy egy csomópont ne legyen túlterhelt egy másikhoz képest.
- Ez lehetővé tenné egy súly hozzárendelését egy csomóponthoz, hogy megbirkózzon a különböző csomópontméretekkel.
- Ez lehetővé tenné tetszőleges (nem sorszámozott) csomópontok elnevezését, hogy támogassa mind a terheléselosztást, mind a shardingot.
Ez az algoritmus sajnos nem létezik. A látottak alapján:
- A Rendezvousnak lineáris időbonyolultsága van keresésenként.
- A gyűrűs konzisztens hash-nak gyenge minimális standard eltérése van a virtuális csomópontok koncepciója nélkül. Virtuális csomópontokkal a térbonyolultság O(n*v), ahol n a csomópontok száma és v a virtuális csomópontok száma csomópontonként.
- A Jump consistent hash nem rendelkezik állandó időbonyolultsággal, és nem támogatja a tetszőleges csomópontok nevét.
A téma még mindig nyitott, és vannak újabb tanulmányok, amelyeket érdemes megnézni. Például a 2005-ben kiadott multi-probe konzisztens hash. Ez O(1) térbeli komplexitást támogat. Mégis, ε standard eltérés eléréséhez O(1/ε) időt igényel keresésenként. Ha például 0,5%-nál kisebb szórást akarunk elérni, akkor a kulcsot körülbelül 20-szor kell hashelni. Ezért minimális szórást érhetünk el, de nagyobb keresési időbonyolultsággal járó erőfeszítések árán.
Amint a bevezetőben említettük, a konzisztens hashing algoritmusok általánossá váltak. Ma már számtalan rendszerben használják, mint például a MongoDB, Cassandra, Riak, Akka stb. legyen szó a terhelés kiegyenlítéséről vagy az adatok elosztásáról. Azonban, mint az informatikában gyakran, minden megoldásnak vannak kompromisszumai.
Apropó kompromisszumok, ha szükséged van a folytatásra, akkor érdemes megnézned Damian Gryski kiváló bejegyzését:
Leave a Reply