Nedávno jsem navštívil přednášku Facebooku Seattle Engineering Road Show, kde Mike Shroepfer a mnoho dalších vývojářů Facebooku poskytli poměrně podrobné informace o technologiích, které Facebook využívá.
V článku jsou mé poznámky z prezentace a odpovědi na nejčastější otázky. Velmi zajímavá byla podobnost architektury pro Facebook newsfeed s aplikací vyvíjenou mým týmem Windows Live What's New Feed.
Vlastní prezentaci předcházela skupina slidů informujících o zajímavých a často působivých statistikách Facebooku:
- Průměrný počet přátel na jednoho uživatele je 130.
- Celkový počet aplikací je 350 000.
- Je jedničkou v oblasti webů uchovávajících fotografie na internetu.
- Je z něj denně odesláno více přání než z Evite.
- Lidé na něm stráví 8 miliard minut denně, což z Facebooku, podle mnoha měřicích služeb včetně Nielsen a ComScore, činí jedničku na webu.
- Nejrychleji narůstá počet lidí nad 35 let.
- Nejvíce fanoušků má stránka Baracka Obamy (6,8 milionů).
- Z televizních show vede South Park.
- 70 % uživatelů nepochází z USA.
Mike Shreopfer začal přednášku množstvím zajímavých statistik. Tyto statistiky obsahovaly např. fakt, že každý týden je sdíleno více než dvě miliardy příspěvků, jako jsou statusy, komentáře, líbí/nelíbí a další. Dále uživatelé nahrají měsíčně na server dvě miliardy fotek, 15 000 implementací připojení k Facebooku v kombinaci s různými platformami vytvoří přes pět miliard volání API denně a okolo 300 milionů aktivních uživatelů měsíčně.
Vytvořit aplikaci jako Facebook je mnohem náročnější než tvorba klasických webových stránek. Běžným způsobem je uložení uživatelských dat do databáze, ze které je v případě potřeby získáváte zpět. Tyto aplikace (např. webmaily) lze snadno rozdělit a lze je přímo horizontálně škálovat rozdělením uživatelů do skupin, které budeme mít rozmístěné na jednotlivé servery. Původní design Facebooku byl velmi podobný. Na počátku měla každá univerzita svůj vlastní cluster (např. http://harvard.facebook.com) a službu šlo velmi jednoduše škálovat. Tento model padl v okamžiku, kdy Facebook umožnil propojení uživatelů mezi univerzitami a odlišnými geografickými sítěmi. Od tohoto okamžiku bylo velmi obtížné dělení dat, protože všichni uživatelé byli propojeni. Pro vytvoření uživatelské homepage nestačí mít pouze data uživatele, ale je třeba získat i data všech jeho přátel. Tyto změny stále představují problém pro škálování Facebooku.
Nejznámější ukázkou takového řešení jsou novinky. Po jejich otevření se na homepage objeví 45 příspěvků. Systém má několik milisekund na zjištění událostí u až 5000 nejbližších přátel a potom musí vybrat 45 příspěvků nejvhodnějších pro uživatele. Pro tento úkol existuje platforma Multifeed, která umožňuje filtrování desítek tisíc položek a vybírá čtyřicet pět pro homepage. Tento proces vyžaduje procházení metadat z cacheovacího clusteru, který zvládne provést přes padesát milionů operací za sekundu. Tyto dotazy obsahují i náročná média, např. fotografie, kterých musí systém obsloužit asi 1,2 milionu za sekundu.
Celkově je nyní v těchto clusterech uloženo více než 20 miliard fotografií, každá ve čtyřech různých rozlišeních (tj. 80 miliard obrázků). V roce 2005 byly fotky ukládány na NFS cluster, což způsobovalo úzká hrdla v systému, protože souborové systémy nejsou uzpůsobeny pro manipulaci s tak velkým počtem souborů. Nakonec bylo metadat příliš, což způsobovalo velké zpomalení systému. Druhá implementace obsahovala několik různých systémů, jako např. přesunutí velkého množství fotografií do Content Distribution Network (CDN). Také byla vytvořena cache pro NFS systém, která snižovala množství I/O operací při hledání souboru na disku. Třetí generací systému pro manipulaci s fotografiemi je úložiště známé jako Haystack. Haystack běží na běžném hardwaru (Dell Linux s terabytovými SATA disky) a používá speciální souborový systém, který udržuje všechny indexy v RAM, což značně urychluje hledání. Současný Haystack je optimalizovaný do té míry, že mu stačí jedna I/O operace pro získání fotografie, v předchozí verzi to byly tři I/O operace a deset pro systém založený na NFS. Flexibilitu Haystacku dokazuje nehoda, při které byl omylem vypnut CDN a Haystack obstaral odesílání fotografií bez jakéhokoliv zdržení. Tato služba byla vytvořena třemi vývojáři během několika měsíců. V brzké době bude uvolněna jako Open Source.
Dalším příkladem, jak přistupuje Facebook ke škálování, je možnost volby tvaru URL pro uživatelský profil. Když byla tato služba spuštěna, měl Facebook přes 200 milionů aktivních uživatelů. Rozpoutalo se mnoho debat, jak uživatelům spravedlivě umožnit získání vhodného uživatelského jména, byla testována i dražba uživatelských jmen. Nakonec se ukázalo, že by to bylo pro uživatele matoucí, a byl zvolen model "kdo dřív přijde, ten dřív mele". Byl očekáván velký nápor uživatelů, kteří si budou chtít zabezpečit své uživatelské jméno, vývojáři se proto připravili podobně jako na útok typu DOS (Denial Of Service). Bylo vytvořeno několik rezervních plánů pro snížení zatížení, jako zmenšení počtu novinek ze 45 na 15 a odesílání statického HTML na některé stránky. Ale žádné z těchto opatření nebylo nakonec nutné použít, protože systém byl nastaven dobře a pracoval bez problémů. Uživatelé si zaregistrovali 200 000 jmen během prvních tří minut, půl milionu během prvních 15 minut a přes milion jmen během první hodiny. Protože uživatelská jména byla vytvářena v rootu jmenného prostoru Facebooku, mnoho uživatelů si zaregistrovalo "vtipná" jména jako http://www.facebook.com/home.aspx, která musela být ručně vyřazena.
Architekturu Facebooku přibližuje následující obrázek:
Web servery s PHP sbírají data z dedikovaných webových služeb, cachí a relačních databází. PHP je využíváno ve front-endu, protože se dá snadno naučit, dobře se v něm pracuje a je velmi výkonné. Samozřejmě, má i své stinné stránky, např. benchmarky ukazují, že je téměř desetkrát pomalejší než tradiční programovací technologie, jako C# a Java. Optimalizaci PHP byla a bude věnována velká pozornost, o přechodu na jiný jazyk se neuvažuje.
Dedikované webové služby jsou postaveny na technologiích, které jsou výhodné pro jejich vývojáře. Zatím existují služby vytvořené v C++, Erlangu, Pythonu a Javě. Bylo také vytvořeno mnoho nástrojů umožňujících snadné a rychlé vytváření nových aplikací. Mezi tyto nástroje patří např. Thrift - vícejazykový RPC framework umožňující komunikaci mezi serializovanými objekty v jazycích C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk a OCaml. Dále existuje Scribe, sbírající logy serverů v real-time režimu, jež následně zveřejňuje na jednom místě. Existují také vnitřní nástroje pro centrální řízení a konfiguraci služeb, monitorování a zasílání upozornění, takže nové služby nemusí tyto věci řešit, ale mohou využít to, co je již hotovo.
Příkladem dedikované vnitřní služby je MultiFeed. Jde o aplikaci, která vezme desítky tisíc updatů uživatelových přátel a zredukuje je na čtyřicet pět položek, které zobrazí na domovské straně zalogovaného uživatele. Jakmile uživatel zveřejní update, je okamžitě zapsán do MySQL i do cacheovacího clusteru pomocí Scribe. V cache je uloženo padesát nejčerstvějších položek od každého uživatele. Když uživatel vejde na svoji stránku, agregátor použije seznam uživatelových přátel a zeptá se na souhrn jejich aktivit. Získaný seznam projde několika filtry a aplikace dostane seznam ID jednotlivých položek. Na základě tohoto seznamu si vyžádá jednotlivé příspěvky z memcache a zobrazí je na domovské stránce.
Multifeed je distribuovaný systém, který vezme desítky tisíc updatů přátel a vybere z nich 45 nejrelevantnějších nebo nejaktuálnějších. Uloží aktuální statusy do databáze a potom je Scribe odešle na Multifeed server, který cachuje padesát nejnovějších akcí uživatele. Takto jsou cacheována data všech uživatelů v systému. Vstupem uživatele do systému se spustí agregátor, který si načte seznam přátel a aplikací série filtrů na jejich záznamy získá seznam ID položek. Potom agregátor získá na základě ID potřebná data z memcache.
Facebook silně využívá memcached, který je distribuovaný jako open source. Jde o hashovací tabulku uloženou v paměti, která odlehčuje MySQL databázím. Vztah k memcache je obojetný. Na jedné straně je spolehlivost, nízká latence a vysoká rychlost. Na druhé straně hrozí snadné porušení dat, datový model má některá omezení a není příliš efektivní pro ukládání malých položek. Byla provedena řada úprav, jako převod na 64-bitovou platformu, přesun z TCP na UDP, optimalizace síťového zásobníku a přidání podpory multithreadingu. Tyto změny zvýšily výkon memcache pětkrát oproti původní verzi.
Jakmile byla dokončena optimalizace memcache, začalo se řešit další úzké hrdlo systému - zahlcování síťových prvků způsobené velkým množstvím odesílaných dat. Tento problém byl způsoben špatným nastavením webserverů, které zasílaly spoustu malých požadavků na data z cache místo jednoho velkého. Byla provedena řada experimentů sledujících velikost dávky požadavků na cachovací cluster a zjistilo se, že nejoptimálnějším řešením je požadovat data z cache v dávkách po 50 položkách. Tento přístup je také použit, když se uživatel pohybuje v aplikační vrstvě. Například místo požadování všech 45 položek najednou je renderována pouze část dat, a teprve když se uživatel dostane na konec stránky, začne se zpracovávat zbytek dat. Snahou je minimalizace cacheovacího clusteru, aby nemusely webové servery komunikovat s velkým množstvím cacheovacích serverů. Aby bylo toto zajištěno, jsou data vertikálně rozdělena podle typu, aby se zabezpečilo, že všechny instance daného typu budou umístěny v malé množině serverů. Protože zde může docházet k chybám, jsou objekty v cache občas replikovány. Pojem replikace popisuje proces, kdy aplikační vrstva přechovává objekty na několika cacheovacích serverech, čímž simuluje replikaci u databází. Když jsem se zeptal, jak je zabezpečena konzistence dat, dostal jsem odpověď, že byl minimalizován počet objektů "replikovaných" tímto způsobem.
MySQL jako databáze byla původně zvolena protože je zdarma, jednoduchá, rychlá a výkonná. Dohromady bylo získáno kolem 6000 serverolet zkušeností bez ztráty nebo poškození dat způsobených chybou softwaru. Ačkoliv většina velkých služeb zvolna končí s používáním MySQL jako úložiště klíč <-> položka a využívá výhodných vlastností relačních databází. Odpověď na otázku, proč si ztěžují práci používáním relačních databází byla, že nástroje ve správě databází, jako je replikace dat nebo administrace, jsou stále velmi výhodné, i když nevyužijete pokročilé funkce, jako jsou např. cizí klíče. Další zajímavou výzvou je využívání "data driven schemas", což programátorům umožňuje přidávat do databáze nové typy bez nutnosti měnit schéma databáze. Tento přístup je velmi podobný tomu, co popisuje Bret Taylor v How FriendFeed uses MySQL to store schema-less data. Problémem tohoto přístupu je nemožnost použít klasické schéma klíč <-> hodnota, protože nelze indexovat důležitá pole, což vede k nemožnosti vytvořit efektivní dotaz.
Jedním z největších nevyřešených problémů je geografická distribuce služeb. V současnosti má Facebook jedno datové centrum na Západním pobřeží a druhé na Východním. Centrum na Západním pobřeží je určeno pro zápis a čtení, kdežto data uložená na Východním pobřeží jsou pouze ke čtení. Takže uživatel v New Yorku při čtení novinek stahuje data z Východního pobřeží, ale při vkládání nového statusu posílá data na Západní pobřeží. Synchronizace dat je zajištěna pomocí replikace MySQL a replikační stream je hacknut tak, aby umožňoval i zasílání příkazů do memcache. Toto chytré řešení hacknutí bylo popsáno na vývojářském blogu Facebooku Jasonem Sobelem pod názvem Keeping Up. Jsou zde stále nevyřešené problémy, jako např. uživateli velmi neoblíbená prodleva způsobená replikací dat (např. když změním svůj status, chci hned vidět, jak to vypadá v mém profilu). Také zůstává otevřená otázka, zda je toto řešení použitelné i v globálním měřítku (tzn. pokud někdy Facebook umístí datové centrum mimo Spojené Státy).
Společnost vytvořila nebo přispěla k obrovskému množství Open Source softwaru. Mimo již dříve jmenovaných technologií, jako Thrift, Scribe a memcached, jsou zde jiné zajímavé projekty organizované Facebookem jako Cassandra a Tornado. Také hodně přispěla k projektu Hive, což je nadstavba software pro distribuované výpočty Hadoop.
Existují tři klíčové mantry popisující vývoj Facebooku:
- Postupuj rychle a průrazně - společnost podporuje lidi v riskování a inovacích, i když ohrožují stabilitu sítě. Je pro ně důležité nebát se riskovat, protože to je často začátek konce.
- Velké výsledky s malým týmem - většina funkcí a základů systému byla vytvořena týmy s jedním až třemi lidmi. Facebook tvrdí, že mají jednoho vývojáře na 1,2 milionu uživatelů, což je lepší poměr než Google (1 vývojář na 190 000 uživatelů), Amazon (1 vývojář na 96 000 uživatelů) a Microsoft (1 vývojář na 75 000 uživatelů).
- Buď odvážný a pokrokový - netřeba vysvětlovat.