揭秘:千里送信為何能到瞬時(shí)到達(dá)

一. 引言
兩百年前,人們想給遠(yuǎn)方的人傳個(gè)話(huà),需要十天半個(gè)月?;ヂ?lián)網(wǎng)時(shí)代,我們只要按下回車(chē),信息秒達(dá),結(jié)果秒出。
那你可曾想過(guò),信息傳送為什么可以這么快?
你可能會(huì)說(shuō),信息以光速級(jí)別傳輸,不論是光纖還是4G/5G用的電磁波,那當(dāng)然快了!
可是,僅僅是光速嗎?那為什么原本掃碼秒出結(jié)果的核酸系統(tǒng),高峰時(shí)一個(gè)人可能卡十幾分鐘;為什么火車(chē)票搶著搶著系統(tǒng)就崩了?
直覺(jué)告訴我們,因?yàn)橛脩?hù)多了,而系統(tǒng)應(yīng)用的承載能力有限。因此,一個(gè)成熟的互聯(lián)網(wǎng)應(yīng)用面對(duì)海量用戶(hù),是練就了十八般武藝(優(yōu)化策略)來(lái)巧妙應(yīng)對(duì)。
其中有些策略的重要性堪比光速,有些也能在日常生活經(jīng)驗(yàn)中找到影子。
二. 整體流程
在介紹優(yōu)化策略前,有必要對(duì)網(wǎng)絡(luò)信號(hào)的請(qǐng)求流程有個(gè)整體印象:
圖1為通過(guò)APP控制攝像頭“轉(zhuǎn)頭”的流程示意圖,大致勾勒了一個(gè)信號(hào)(網(wǎng)絡(luò)請(qǐng)求)的典型旅程。

圖1 網(wǎng)絡(luò)傳輸流程
簡(jiǎn)單來(lái)說(shuō),一個(gè)網(wǎng)絡(luò)請(qǐng)求的耗時(shí)主要來(lái)自網(wǎng)絡(luò)傳輸、數(shù)據(jù)中心處理。
具體來(lái)說(shuō),APP上點(diǎn)擊按鈕-->“轉(zhuǎn)頭”指令等信息,會(huì)被轉(zhuǎn)化為0和1的二進(jìn)制序列-->手機(jī)通過(guò)內(nèi)置天線發(fā)射電磁波-->基站-->運(yùn)營(yíng)商機(jī)房-->通過(guò)光纖傳送到千里之外的數(shù)據(jù)中心(圖1)。
數(shù)據(jù)中心存放著系統(tǒng)的云端平臺(tái)。平臺(tái)處理后,將“轉(zhuǎn)頭”指令發(fā)出-->光纖傳輸-->到家中路由器,通過(guò)無(wú)線信號(hào)發(fā)給攝像頭-->攝像頭接收信號(hào)并轉(zhuǎn)為0和1的序列-->還原為攝像頭軟件可理解的指令-->操控電機(jī)進(jìn)行旋轉(zhuǎn)。

圖2 數(shù)據(jù)中心的平臺(tái)組成
一眨眼的功夫,就完成了這么多環(huán)節(jié)(實(shí)際過(guò)程遠(yuǎn)比此復(fù)雜)。
從中可見(jiàn),光速解決的僅僅是長(zhǎng)距離傳輸?shù)暮臅r(shí)問(wèn)題,如果哪個(gè)節(jié)點(diǎn)卡住,效率直線下降,就如同短板木桶,盛水能力將大打折扣。
優(yōu)化策略有很多,本文將介紹其中最為關(guān)鍵的4種:索引,緩存,負(fù)載均衡,并發(fā)。
三. 優(yōu)化策略
3.1 索引
索引可以說(shuō)是非常偉大的發(fā)明了。用一句話(huà)說(shuō)就是:事先分類(lèi)排序,到時(shí)找起來(lái)方便。比如查字典,咱都是按索引查,如果沒(méi)索引,從頭找到尾可要累死個(gè)人。
數(shù)據(jù)中心里的數(shù)據(jù)庫(kù),幾千萬(wàn)條數(shù)據(jù)也是司空見(jiàn)慣了。以mysql為例,用的索引方案一般是B+樹(shù),找一條數(shù)據(jù)1~4次即可找到,耗時(shí)約幾十毫秒。而如果沒(méi)有索引則需要遍歷,可能十幾秒才能找到,差距達(dá)數(shù)百倍。
相信大家用過(guò)windows自帶的文件搜索,慢得令人無(wú)語(yǔ);如果用everything等軟件則瞬間出結(jié)果,正體現(xiàn)了索引的強(qiáng)大威力。(注:windows不是完全不用索引,是沒(méi)用合適的索引)
當(dāng)然索引并非全無(wú)代價(jià):占存儲(chǔ)空間;索引樹(shù)時(shí)常變化,引起性能消耗。雖有代價(jià),但非常值得,正所謂磨刀不誤砍柴工嘛。
計(jì)算機(jī)的世界,索引無(wú)處不在,此處囿于篇幅不展開(kāi)詳述,若感興趣詳見(jiàn)文末表格。正是每個(gè)環(huán)節(jié)盡可能地用上索引,用巧妙的“速達(dá)”取代笨拙的“遍歷”,才讓一次請(qǐng)求盡可能地快。
3.2 緩存
為什么廚房的鹽、味精要從調(diào)料盒里舀取,而不從包裝袋里舀?因?yàn)閺恼{(diào)料盒舀取方便、快。
為什么某東自營(yíng)的快遞那么快?全國(guó)各大倉(cāng)庫(kù)就近發(fā)貨嘛。
以上便是計(jì)算機(jī)緩存的兩種思路:把常用的數(shù)據(jù)拷貝到速度更快的地方,或離用戶(hù)更近的地方,這樣拿數(shù)據(jù)就快多了。

圖3 計(jì)算機(jī)各類(lèi)耗時(shí)
上圖是計(jì)算機(jī)各部件單次訪問(wèn)的耗時(shí),可見(jiàn)網(wǎng)絡(luò)傳輸、硬盤(pán)的耗時(shí)是大頭,所以這兩者能免則免。
數(shù)據(jù)中心里,還是以數(shù)據(jù)庫(kù)(Mysql)為例:它的全部數(shù)據(jù)存在硬盤(pán)上,但會(huì)將常用的熱點(diǎn)數(shù)據(jù)拷到內(nèi)存的緩沖池里,讀寫(xiě)都在緩沖池,力求減免跟硬盤(pán)打交道而拖累整體效率。
這跟咱們寫(xiě)文檔的情況是一樣的:打開(kāi)文檔時(shí)文字被加載到電腦內(nèi)存,新寫(xiě)的文字也記錄到內(nèi)存。
萬(wàn)一電腦或程序崩潰卻沒(méi)保存,那新寫(xiě)的可能就丟了,就是因?yàn)樾聦?xiě)的還沒(méi)來(lái)得及存到硬盤(pán)上呢(內(nèi)存斷電后數(shù)據(jù)會(huì)消失,而硬盤(pán)不會(huì))。
數(shù)據(jù)庫(kù)則無(wú)需擔(dān)心,它有額外機(jī)制確保數(shù)據(jù)的改動(dòng)不丟失,即預(yù)寫(xiě)式日志:每次操作在硬盤(pán)里簡(jiǎn)單記錄下對(duì)硬盤(pán)的修改結(jié)果,這樣即使沒(méi)保存事后也能恢復(fù)。
打個(gè)不太恰當(dāng)?shù)谋确?,就像咱上課除了認(rèn)真聽(tīng)還要好好做筆記,即使課后有的忘了,也能根據(jù)筆記想起來(lái)。
3.3 負(fù)載均衡
俗話(huà)說(shuō)得好:人多力量大。負(fù)載均衡就是以量取勝,通過(guò)增加節(jié)點(diǎn)來(lái)分?jǐn)倝毫ΑI钪?,像食堂如果有很多窗口都能排?duì),是不是排隊(duì)時(shí)間就短多了呢?
數(shù)據(jù)中心里,需要有負(fù)載均衡器(如Nginx)來(lái)起到對(duì)請(qǐng)求分流的作用,將請(qǐng)求轉(zhuǎn)發(fā)到各后端節(jié)點(diǎn)。
面對(duì)流量高峰,后端節(jié)點(diǎn)的數(shù)量擴(kuò)展如今挺方便,只要平臺(tái)實(shí)現(xiàn)了容器化部署,加節(jié)點(diǎn)就是點(diǎn)幾下按鈕的事。
數(shù)據(jù)庫(kù)也能負(fù)載均衡,即分庫(kù)分表,將一張大表拆分成若干小表,分散到各機(jī)器上。正所謂船大難掉頭,改成若干艘小船當(dāng)然就輕松靈活了。
但分庫(kù)分表不是點(diǎn)幾下按鈕就能解決的,它涉及到數(shù)據(jù)遷移、改代碼、測(cè)試、上線。因此數(shù)據(jù)庫(kù)的擴(kuò)容,需要未雨綢繆,早做謀劃;否則流量高峰期系統(tǒng)可能被沖垮,這樣所有人都用不了了。
3.4 并發(fā)
雖說(shuō)人多力量大,但個(gè)體太弱也不行。如何讓個(gè)體變強(qiáng),即如何提升單臺(tái)服務(wù)器的性能呢?
并發(fā)是一種思路。如今的計(jì)算機(jī)可以同時(shí)放歌、聊微信、下載視頻,似乎這對(duì)于萬(wàn)能的計(jì)算機(jī)是理所當(dāng)然的。
然而,早期的計(jì)算機(jī),同一時(shí)間只能運(yùn)行一個(gè)軟件、給一個(gè)用戶(hù)用,相當(dāng)不方便。
后來(lái)分時(shí)操作系統(tǒng)解決了這個(gè)問(wèn)題,原理是將CPU的時(shí)間分成一片片(幾十到幾百毫秒),輪流分給不同的軟件使用(此處指單核CPU)。這體現(xiàn)了并發(fā)的思想:若干事件微觀上先后輪流進(jìn)行,但宏觀表現(xiàn)為同時(shí)進(jìn)行。
你可能想,這不是騙人嗎,而且每個(gè)軟件的效率會(huì)明顯降低吧?
其實(shí),一個(gè)軟件(或進(jìn)程)不是一直占著CPU,很多時(shí)候是在休息(即阻塞),比如讀寫(xiě)硬盤(pán),等待網(wǎng)絡(luò)請(qǐng)求的回應(yīng)。此時(shí)CPU閑著也是閑著,拱手讓給其他軟件用豈不美哉。
就如泡茶問(wèn)題:等水燒開(kāi)期間去洗茶杯、放茶葉才是明智之舉,而不是等水燒開(kāi)了再干活。
因此,操作系統(tǒng)的這種時(shí)間分片輪流使用的策略,一方面充分利用了CPU;另一方面,即使是一個(gè)真的連續(xù)干活的任務(wù)拆解為若干次分散執(zhí)行,多數(shù)情況下人宏觀上也感知不到微觀層面的這種卡頓。
3.5 CPU
最后補(bǔ)談一個(gè)重要因素:CPU。
你可能聽(tīng)說(shuō)過(guò)現(xiàn)在的軟件可復(fù)雜了,動(dòng)不動(dòng)幾十萬(wàn)行代碼。實(shí)際上一次網(wǎng)絡(luò)請(qǐng)求涉及的代碼也是不計(jì)其數(shù),而這一切在短短幾(十)毫秒內(nèi)就能完成,已經(jīng)不是人的思維能跟得上的了。
這實(shí)際上離不開(kāi)CPU的高性能。如今常見(jiàn)CPU一秒可以執(zhí)行幾十億次指令,而它誕生之初只能幾十萬(wàn)次。如果沒(méi)有CPU的高速,互聯(lián)網(wǎng)精巧而龐雜的體系也無(wú)從談起了。
比如你盯著屏幕的這一刻,無(wú)論手機(jī)還是電腦,幕后英雄CPU正以我們無(wú)法想象的風(fēng)馳電掣在干各種活。
當(dāng)然,也不是CPU頻率越高就意味著軟件的性能越好,影響因素有很多,因此相信國(guó)產(chǎn)CPU后來(lái)居上也是有希望的。
四. 結(jié)語(yǔ)
用一個(gè)簡(jiǎn)圖(圖4)概括本文:光速是“瞬時(shí)”傳輸?shù)谋匾獥l件;如果用戶(hù)多處理不過(guò)來(lái),那就通過(guò)負(fù)載均衡增加節(jié)點(diǎn);每個(gè)節(jié)點(diǎn)都能利用索引、緩存、并發(fā)來(lái)大幅提升性能;而CPU,又是鏈路上所有節(jié)點(diǎn)能夠快速處理的基礎(chǔ)。

圖4 網(wǎng)絡(luò)請(qǐng)求的優(yōu)化策略
網(wǎng)絡(luò)請(qǐng)求的優(yōu)化策略遠(yuǎn)不止上文提到的,還有IO多路復(fù)用、池化、批量處理、削峰填谷等等,都不容小覷。
本文提到的網(wǎng)絡(luò)鏈路上各環(huán)節(jié)的優(yōu)化策略的舉例,匯總?cè)缦卤恚?/p>
表1 網(wǎng)絡(luò)請(qǐng)求鏈路上各環(huán)節(jié)的優(yōu)化策略舉例





















