再拉遠一級鏡頭
回頭看看我們走了多遠。我們從一顆當開關用的電晶體起步,把開關疊成邏輯閘,把閘疊成資料路徑,在它外面包上一套指令集,用管線和亂序執行引擎加速它,透過一座快取階層餵它,最後把許多核心栓進同一顆晶片。每一級都是一次拉遠鏡頭:同一台機器,用更粗的顆粒去看。這一級不過是最後一次拉遠。我們走出晶片、走出伺服器,去看一整棟建築。
當你向搜尋引擎問一個問題、打開一張地圖、或串流一段影片時,你的請求並不會落在一台電腦上。它落進一台倉庫級電腦(WSC):一棟容納了上萬台伺服器的建築,靠網路與軟體編織在一起,使整座東西表現得像單獨一台巨大的機器。這個點子——由設計 Google 早期基礎設施的工程師發揚光大——是把資料中心,而不是伺服器、不是晶片,當成設計的單位。你不是去買一台更快的電腦;你是去設計一棟更好的建築。
它不是超級電腦
把 WSC 想像成一台特別大的超級電腦,是很誘人的,但這兩者解的是相反的問題,所以蓋法也相反。經典的超級電腦跑一個巨大、緊密耦合的工作——模擬一個星系、折疊一個蛋白質——其中每個節點都得透過一種奇特、快得灼人的互連,不停地和鄰居對話,而一個慢節點就會拖垮整場計算。WSC 跑的卻是數百萬個彼此獨立的工作:你的搜尋、我的電郵、她的影片,全都同時進行,多半互不知曉。
工作型態的這個差異,一路下探到零件清單。超級電腦精緻又昂貴:最快的客製處理器、最奇特的網路。WSC 卻是刻意用商規硬體蓋成——平凡、量產的伺服器,挑能把事辦成的最便宜那一款,整卡車整卡車地買。為什麼甘於平凡?因為到了這個規模,經濟學主宰一切:當你需要十萬個某物時,為了多十趴的速度而每台多付一倍的錢,是一筆災難性的交易。你贏的辦法,不是讓每台機器都卓越,而是讓整支機隊便宜,並且容忍便宜零件保證會帶來的那些故障。
白送上門的平行性
回想在單一晶片上,平行有多難。執行緒爭搶一致的快取,只要還剩下任何序列部分,Amdahl 定律就立刻替你的加速封頂,而偽共享能悄悄毀掉兩個更新相鄰格子的核心。WSC 享有一種較輕鬆的平行,幾乎是天上掉下來的:請求級平行。十億個使用者送出十億個互不相干的請求,每個都能在自己的機器上被處理,從不必和其他請求協調。沒有共享的可變狀態可爭搶,所以這種工作橫向擴展到數千台伺服器,比執行緒擴展到多核心優雅得多。
當一個工作真的巨大——比方說,替整個網路建索引——訣竅是把它剁成數千個獨立的碎片,撒到整支機隊上。經典的食譜是 MapReduce:一個映射(map)步驟,在每一塊資料上平行地跑同一個小函式,接著一個歸約(reduce)步驟,把部分答案合併起來。數遍網路上每個字,就變成:把每一頁映射成一堆 (字, 1) 配對,就在持有那一頁的機器上做,然後對每個字把計數加總起來歸約。像 Spark 這樣的框架把同一個點子一般化了。我們會在下一篇導覽裡把它打開;現在的重點是,資料級平行——在單機上屬於 SIMD 與 GPU 的領地——在這裡以整棟建築的規模重新登場。
建築的形狀
拉近來看,WSC 有它自己的階層,呼應你已經熟悉的記憶體階層——又小又近 對上 又大又遠,而隨著你伸得越遠,成本就升高。一台伺服器是一台平凡的機器。幾十台伺服器疊成一個機架(rack),共用單一一台架頂交換器,便宜又快速地把它們連起來。幾十個機架組成一個叢集(cluster),由一張更大的、由匯聚交換器構成的資料中心網路接合。跟你自己機架裡的伺服器對話,又快又幾乎免費;跨越整棟建築的對話,要穿過更多交換器,花更多時間。就像從 L1 伸到 DRAM 一樣,區域性很重要——當一個工作的資料就坐在同一個機架裡時,它跑得最好。
level what it is rough size talk to it... --------- ------------------ ------------- ---------------------------- server one commodity box 1 machine within itself: nanoseconds rack servers + ToR switch ~ 40 servers same rack: ~ microseconds cluster racks + network ~ 1000s servers across building: slower WSC the whole building ~ 10k-100k+ another datacenter: ~ ms Reaching farther costs more time and crosses more switches -- the same small-near / big-far shape as the memory hierarchy.
在這個規模上,冒出一個尖銳的新問題:尾端延遲。單一個使用者請求常常會扇出到數百台伺服器——各自搜尋索引的不同切片——而答案要等到它們之中最慢的那台回覆了,才能送回來。就算每台伺服器有 99% 的時間都很快,當扇出有數百台時,「至少有一台」撞上它罕見的慢情況的機率就很高。於是請求要等那個最倒楣的回應者,而使用者感受到的是第 99 百分位的延遲,不是平均值。馴服這條尾巴是如此核心,以致它在這一級稍後會獨得一篇導覽。
故障不是事件——它是天氣
在你的筆電上,一次當機是一件你會記住的事件。在一棟有十萬台便宜機器的建築裡,總是有東西壞掉:一顆磁碟死了、一個電源供應器掛了、一顆記憶體晶片翻了一個位元、一台交換器重開機。零件這麼多,就算每台機器的壽命再寬裕,也意味著每一天都有好幾次故障。於是 WSC 設計者做了一個硬核的哲學轉向:別再試圖預防故障,而是把它當成像下雨一樣的常態來假設。系統必須在它的零件正不斷死去又被替換的同時——一天的每個鐘頭——持續正確地服務。
答案是系統層級、而非零件層級的冗餘。你不去買一台超可靠的伺服器;你保留許多便宜的副本,並繞過死掉的那些。把每個檔案存在三台機器上,於是失去一台等於什麼也沒失去。把每個服務跑在負載平衡器後面的許多複本上,於是一次死亡只意味著少了一個工人。整座大廈都為優雅降級而設計:當一個機架壞了,建築不會倒——它只是服務得稍慢一點、或容量少一點,而維修班按自己的排程把零件換掉。這同一個直覺——用不可靠的零件買到整體的可靠——正是你在 I/O 那一級遇過的 RAID 與錯誤更正碼的精神,如今擴展到一棟建築的尺度。為持續故障而設計,在這裡也獨得一篇導覽。
帳單就是電費
這部分讓新手吃驚。一台 WSC 終其一生最主要的成本,不是伺服器——而是電力,以及為了輸送電力而建造供電與冷卻廠的成本。一座大型資料中心吃掉數十百萬瓦,足以供應一座小鎮,而晶片燒掉的每一瓦特,都變成熱,又得用更多的電去把它抽走。營運者用總體擁有成本(TCO)來算帳:不是貼紙上的價格,而是硬體、電力、冷卻、建築與人力在整個生命週期裡的總和。在這面鏡頭下,一顆稍微更省電的晶片,可能比一顆更快的晶片更值錢,因為電費是一年又一年、每一秒都在付的。
兩個數字概括了能源的故事。PUE——電力使用效率——是建築總用電除以真正抵達電腦的那份電力。PUE 為 2.0,意味著每一瓦的運算就要再討一瓦去做冷卻與損耗,那是一棟浪費的老建築;最好的現代資料中心把 PUE 壓到接近 1.1,幾乎把每一分電都花在真正的工作上。第二個數字是能耗比例性:理想上,一台負載 10% 的伺服器,應該只吃掉它尖峰功率的 10%。真實的伺服器很不擅長這件事——一台閒置的機器仍可能燒掉它尖峰的一半——這很浪費,因為在 WSC 裡,大多數伺服器多數時間都處在中低負載。追求比例性、重用功率那一級的電壓與頻率調節技巧,是這個領域一場安靜而昂貴的戰役。