Mármint techikailag: miért van ennyi leállás, milyen problémák vannak a háttérben? A választ elég jól összefoglalja a ReadWriteWeb, ebből kiinduló, de saját hasonló jellegű tapasztalatokkal fűszerezett összefoglaló következik.

Nos, az első és legnagyobb gond az, hogy a Twitter nem arra lett tervezve, mint amire ma használjuk. Egy CMS szerű felépítésben gondolkodtak a fejlesztők, ahol a skálázhatóság megoldása a cache volt – kb.: egy hozzászólás után töröljük a cache-t, majd generáljuk le az oldalt megint. A Twitterből azonban nem CMS nőtt ki, hanem egy üzenetküldő platform, a gyakori frissítések használhatatlanná tették ezt a cache-elési módszert (ugyanis nem csak a saját oldalunk cache-ét kell törölni, hanem minden olyan oldalt, ahol “követ” minket a tulajdonos). A probléma nem kis látogatottságnál, hanem extrémnél van – de ez az amivel a Twitter ma küzd, ráadásul nem beálló, hanem folyamatosan növekvő látogatottságról van szó. És ez az architektúra sajnos nem igazán skálázható ezzel a felhasználási körrel – egyáltalán.
A skálázhatóság problémája ott kezdődik, hogy vajon hogyan tároljuk le ezeket az adatokat. Itt hozom be a személyes tapasztalatokat, konkrétan a Miner.hu-t mellékleteket. Mind a Twitter, mint a mellékletek esetében egy jó nagy adatbázisról beszélünk (Minernél ez 8 millió sor, Twitternél inkább ne is akarjuk tudni). melyből ki kell válogatni bizonyos tulajdonságú elemeket (Twitternél adott felhasználó és barátai csiripjeit, Minernél az adott melléklet blogjaihoz tartozó bejegyzéseket). Ha a lekérdezés eredményét illetően nincs sok elemről szó, akkor nincs hatalmas gond, az adatbázisszerver gyorsan összemixeli az elemeket (felhasználónként, blogonként), és kiköpi magából. A Minernél a film melléklettel indult a gond, aholis bár viszonylag kevés bloggal indultunk, de az egyes blogokban (comment:com, sorozatjunkie) rengeteg bejegyzés szerepelt visszamenőleg, melyek (indexei) már nem fértek bele a memóriába a lekérdezéskor, és elkezdett diszket használni a MySQL. Ugyanez a jelenség a Twitternél is fennáll – memóriaigényes összefésülni különböző felhasználók csiripjeit. Míg a Minernél viszonylag kevés melléklet van, ezért megoldást jelentett az, hogy egy külön táblában is indexeljük a mellékletek bejegyzéseit (így direktben használhatóak indexek, nincs több blog összefésülése), a Twitternél ez nem jó megoldás, hiszen rengeteg felhasználónál, rengeteg fajta leválogatást kell összehozni. Vagy mégis?
Erre a problémára az adatok duplikációját, az adatbázis denormalizációját szokták megoldásként felhozni, avagy egy olyan megoldás jöhet szóba, mely amikor hozzászól valaki egyet, akkor az adott felhasználó adatbázisába történő bejegyzés mellett a többi, őt követő felhasználó adatbázisába is felveszi a hozzászólást. Ez elsőre gyilkosnak tűnhet, de egyrészt ugye a hozzászólás maximum 140 karakter környékén lehet, tehát nincsen szó hatalmas adattárolási igényekről, másrészt pedig az egyes felhasználók adatbázisát jópár különböző szerverre szét lehet szórni, így párhuzamosítható a művelet. Másrészt mostanában divatos nem relációs adatbázisokra építő, jól skálázható elosztott adatbázisok (cloud computing – ismerős?) pont kiválóan használhatóak így.
Persze nem tudom, hogy a Twitter valóban ilyen megoldást választ-e, s hogy pont ilyen problémákkal küzd-e éppen, de valószínűleg – s ebben a belinkelt RWW-s bejegyzés is megerősít – nem olyan messze áll a fentiektől a valóság.
Nagyon korrekt kis cikk, köszi!
http://arstechnica.com/news.ars/post/20080523-on-twitter-architecture-and-laying-in-the-grass.html
Találgatás helyett tessék kattintani, érdekes; CMS és rewrite rész különösképp.
Aztán rájöttem, hogy nem mond sokkal többet
Meglátjuk, mit találnak ki a fiúk – ha semmit, akkor úgyis jön valaki és betölti a Twitter helyén keletkező űrt. Amúgy elosztott adatbázisokhoz, úgy érzem, nálunk is kéne némi segítség…
deadcabbit: Kb. ugyanaz van benne, hiszen a Twitteres blogbejegyzésre hivatkozik ez is. A cache megoldásukat illetően csak részben találgatok, azért látszott kívülről, hogy valami ilyesmit használnak. Nekik most tényleg újra kell írniuk az egész rendszert úgy, hogy közben nincsen leállás, egyszerűen a jelenlegi rendszer nem skálázható megoldás.
Cal Henderson (Flickr) szint minden prezentációjában szerepel egy fontos mondat: Database Normalization Is for Sissies…
Ha valaki tényleg komolyan gondolja, hogy a globális hatalomátvétel a célja, akkor érdemes párszor átlapozgatni a srác prezentációit illetve könyvét.
Mi a baj a Netvibessal mikor lesz? Vagy irjak rola?
http://benjamin.hu/tmp/netvibes.error.gif
Benjamin: Ha gondolod írj róla!
A Netvibes-szal is hasonlóak a gondok, bár itt főként az, hogy nem számítottunk ekkora érdeklődésre a Ginger után. A képen ugyan nem látszik mi a gond, de valahol mintha írtad volna, hogy a régi elemek olvasatlanok lesznek hirtelen. Ezt a hibát láttam már előfordulni a hibakövető rendszerünkben, talán már ki is van javítva. Konkrét leállásról az utóbbi időben nem tudok.
Messze nem vagyok benne biztos, hogy a twitter esetében nyerő lenne a fentebb említett denormalizálás. Elég sokan követgetik egymást, nagyon sokszor kéne ugyanazt az adatot sok helyen letárolni.
Szerintem esetükben inkább olyasmi lehet nyerő, hogy a kapcsoló táblák vannak csak szétterítve, maguk az üzenetek pedig durván cachelve vannak. Magukat a usereket listafrissülésük szerint lehet különböző osztályokba sorolni, adott esetben lehet a teljes lisátkat is cache-elni.
Plusz még lehet csalni azzal is, hogy nem egyből jelenik meg egy hozzászólás, így elérhető, hogy sok kérés full cache-ből legyen kiszolgálva, míg egy másik nagy részük esetén magukat az id-kat kell csak DB-ből leszedni (ami mondjuk InnoDB clustered index esetén piszok gyors tud lenni), és az üzenetek pedig külön memcacheből jönnek elő.
Plusz még ez is érdekes lehet: http://dev.twitter.com/2008/05/twittering-about-architecture.html
Üdv,
Felhő
Hodicska Gergely: amit belinkeltél, az összes fenti link arra hivatkozik és azt elemzi – mondjuk pont ezt nem sikerült belinkelni edddig, szóval kösz.
Szerintem 140 byte letárolása sok helyen nem okoz gondot. Cache-elni, késleltetni egyszerűen nem lehet, az API felhasználók egyből észrevennék, sok az API-ra épülő alkalmazás használhatatlanná válna. Egyébként nagyon hasonló megoldásról beszélünk másképpen – csak éppen a memóriába biztosan nem fér el az összes üzenet, amit egy API lekérdezés jellemzően visszaadhat, és a jelenlegi API forgalom iszonyatosan nagy lehet. Memóriában tárolt megoldásra építeni (mármint megpróbálni berakni a memóriába az összes friss hozzászólást) szerintem hosszútávon gyilkos megoldás, gyorsabban fejlődhet a Twitter, mint a memóriák. Elosztani el lehet persze, a friss elemeket is, de szerintem valamilyen ügyes denormalizálás lehet a megoldás.
Jelenleg csak az utolsó 10(?) elem érhető el egy felhasználó csiripel
“Cache-elni, késleltetni egyszerűen nem lehet”: a második felére nem tudok mit mondani, mert az valamilyen szinten üzleti döntés, viszont az elős felére: pár másodperces cache már csodákra lehet képes, és a legtöbb feed esetén azért van pár (több) másodperc amíg nem frissül.
“csak éppen a memóriába biztosan nem fér el az összes üzenet”
“Memóriában tárolt megoldásra építeni (mármint megpróbálni berakni a memóriába az összes friss hozzászólást) szerintem hosszútávon gyilkos megoldás, gyorsabban fejlődhet a Twitter, mint a memóriák.”
Facebooknál 800 DB csak memcache szerver van, elég sok minden el tud férni benne.
“Egyébként nagyon hasonló megoldásról beszélünk másképpen”
“szerintem valamilyen ügyes denormalizálás lehet a megoldás”
Csak azt nem értem, hogy ezzel a megoldással jóval több melót adsz a DB-nek. Az üzeneteket magukat is szét kell teríteni, plusz így kvázi a DB-be cache-elnél, viszont a DB-ből kiszedni egy adatot az jóval bonyolultabb “protokol”, mint memcache-ből kiszedni, tehát még a query cacheből is lassabban jön ki egy adat.
Üdv,
Felhő
Hodicska Gergely: De ha pár másodperces cache csodákra képes, akkor miért ne legyen folyamatos a “cache”, avagy legyen eleve terítve az információ? “adatbázis” alatt pedig nem relációs adatbázisszervert értek, beszélhetünk memcache alapú adatbázisról is ami a szétszórást illeti. ezért mondom hogy elég közel vannak egymáshoz az elképzeléseink.
“csak éppen a memóriába biztosan nem fér el az összes üzenet”
“beszélhetünk memcache alapú adatbázisról is ami a szétszórást illeti.”
Itt azért érzek némi ellentmondást.
Üdv,
Felhő
Hodicska Gergely: Szerintem hagyjuk, ha nem akarod érteni. Én azt mondom hogy (mondjuk) az utóbbi 24 óra összes csiripjei nem fér bele _egy_ szerver memóriájába, egy adott felhasználói halmaz bejegyzései viszont simán. Innentől az a kérdés hogy mi a gyorsabb/hatékonyabb/működőképes, összelapátolni indexek alapján a felhasználói bejegyzéseket akár külön szerverekről (ahogy te mondod), vagy pedig előre összeállítani úgy, hogy 0 erőforrást igényeljen, és egy szerveren meglegyen minden. A twitter akkorára nőtt, hogy az előbbi szerintem egyszerűen nem működik.
Én tisztán értelek, csak nem értek egyet. Próbáld ki egyszer, hogy mekkora különbség van mysqlből lekérni valamit és mennyi memcacheből. Kb. nagyságrenddel gyorsabb a memcache. (Ettől függetlenül az a két idézett sor üti egymást.
)
“utóbbi 24 óra összes csiripjei nem fér bele _egy_ szerver memóriájába”
Egyrészt nem is kell egy szerver memóriájába beférjen, memcache alapból megoldja neked, hogy elosztja az adatokat több szerver között.
Másrészt vegyünk mondjuk 8GB memóriát (ami simán nem sok, ennek többszöröse lehet egy szerverben), ha 200 byte-ot veszünk egy üzenet memória foglalására (járulékos költségek), akkor is több mint 40 millió üzenet simán elfér benne, bőven ez alatt van a twitter napi termelése.
Plusz én nem azt vázoltam, hogy az üzeneteket össze kell szedni különböző szerverekről, hanem azt, hogy NÉHA. Alapban DB-ben tárolod az adott node usereit, plusz minden usernek az ő listájához tartozó üzenet azonosítókat. Ezen kívül tárolunk teljes listákat is memcacheben (ezt innen lekérdezni lénegesen gyorsabb, mint DB-ből). Ha itt nincs meg, akkor kérem le DB-ből az ID-kat, és ezek alapján kérem le memcacheből az adatokat, és leteszem a listát memcachebe, legközelebb onnan szolgálom ki. Cache invalidálást nagyon könnyen meg lehet oldani, akár DB trigger kiütheti, de egyéb okos megoldásokat ki lehet találni a részletek fényében. És a memcahe-nek ami még nagy előnye, hogy automatikusan megoldja neked, hogy a legfontosabb (leggyakrabban) használt elemek vannak a cache-ben.
Üdv,
Felhő