單機架構(gòu)
網(wǎng)站初時,應(yīng)用數(shù)量和用戶量都極少胎许,可以把應(yīng)用程序和數(shù)據(jù)庫部署在同一臺服務(wù)器上鹤竭。
第一次演進:應(yīng)用與數(shù)據(jù)庫分離
應(yīng)用與數(shù)據(jù)庫對資源的消耗不同,分開部署在獨立的服務(wù)器上能顯著提高兩者各自性能拷呆。
隨著用戶數(shù)的增長,并發(fā)讀寫數(shù)據(jù)庫成為瓶頸
第二次演進:引入緩存
緩存能把絕大多數(shù)請求在讀寫數(shù)據(jù)庫前攔截掉,大大降低數(shù)據(jù)庫壓力茬斧。
使用分布式緩存腰懂,例如 Redis,會涉及到緩存一致性项秉、緩存穿透/擊穿绣溜、緩存雪崩、熱點數(shù)據(jù)集中失效等問題
緩存抗住了大部分的請求訪問娄蔼,隨著用戶數(shù)的增長怖喻,并發(fā)壓力主要落在單機的應(yīng)用服務(wù)器上,響應(yīng)逐漸變慢
第三次演進:引入反向代理實現(xiàn)負(fù)載均衡
在多臺服務(wù)器上部署應(yīng)用服務(wù)岁诉,使用反向代理把請求均勻分發(fā)到每個應(yīng)用服務(wù)中
使用反向代理涉及的技術(shù)包括:Nginx等反向代理軟件锚沸,Session共享、文件上傳下載問題
反向代理使應(yīng)用服務(wù)可支持的并發(fā)量大大增加唉侄,但高并發(fā)的增長也意味著更多請求穿透到數(shù)據(jù)庫咒吐,單機數(shù)據(jù)庫最終成為瓶頸
第四次演進:數(shù)據(jù)庫讀寫分離
把數(shù)據(jù)庫劃分為讀庫和寫庫野建,讀庫可以有多個属划,通過同步機制把寫庫的數(shù)據(jù)同步到讀庫,對于需要查詢最新寫入數(shù)據(jù)場景候生,可通過在緩存中多些一份同眯,通過緩存獲得最新數(shù)據(jù)。
其中涉及到的技術(shù)問題:Mycat數(shù)據(jù)庫中間件唯鸭,組織數(shù)據(jù)庫的分離讀寫和分庫分表须蜗。數(shù)據(jù)同步、數(shù)據(jù)一致性問題
業(yè)務(wù)逐漸變多目溉,不同業(yè)務(wù)之間的訪問量差距較大明肮,不同業(yè)務(wù)直接競爭數(shù)據(jù)庫,互相影響性能
第五次演進:數(shù)據(jù)庫按業(yè)務(wù)分庫
把不同業(yè)務(wù)的數(shù)據(jù)保存到不同的數(shù)據(jù)庫中缭付,使業(yè)務(wù)之間的資源競爭降低柿估,對于訪問量大的業(yè)務(wù),可以部署更多的服務(wù)器來支撐陷猫,這樣同時導(dǎo)致跨業(yè)務(wù)的表無法直接做關(guān)聯(lián)分析秫舌,需要通過其他途徑來解決。
隨著用戶的增長绣檬,單機的寫庫會逐漸達到性能瓶頸
第六次演進:把大表拆分為小表
比如針對評論可以按照商品ID進行hash足陨,路由到對應(yīng)的表中存儲;針對支付記錄娇未,可按小時創(chuàng)建墨缘,每個小時表繼續(xù)拆分為小表,使用用戶ID或記錄編號來路由數(shù)據(jù)。只要實時操作的表數(shù)據(jù)量足夠小飒房,請求能夠足夠均勻的分發(fā)到多態(tài)服務(wù)器的小表上搁凸,那數(shù)據(jù)庫就能通過水平擴展的方式來提高性能。
數(shù)據(jù)庫設(shè)計到這種結(jié)構(gòu)時狠毯,已經(jīng)可以稱之為分布式數(shù)據(jù)庫护糖。數(shù)據(jù)庫里不同的組成部分是由不同的組件單獨來實現(xiàn)的,如分庫分表的管理和請求分發(fā)嚼松,由Mycat實現(xiàn)嫡良;SQL的解析由單機的數(shù)據(jù)庫實現(xiàn);讀寫分離可能由網(wǎng)關(guān)和消息隊列來實現(xiàn)献酗;查詢結(jié)果的匯總有數(shù)據(jù)庫接口層來實現(xiàn)等等寝受,這種架構(gòu)其實是MPP(大規(guī)模并行處理)架構(gòu)的一類實現(xiàn)
MPP數(shù)據(jù)庫開源比較多:Greenplum、TiDB罕偎、Postgresql XC很澄、HAWQ等。不同的MPP數(shù)據(jù)庫的側(cè)重點也不一樣颜及,如TiDB更側(cè)重于分布式OLTP場景甩苛、Greenplum更側(cè)重于分布式OLAP場景。
數(shù)據(jù)庫和應(yīng)用程序都能夠水平擴展俏站,可支撐的并發(fā)大幅提高讯蒲,隨著用戶數(shù)的增長,最終單機的Nginx會成為瓶頸
第七次演進:使用LVS或F5來負(fù)載均衡
由于瓶頸在Nginx肄扎,因此無法通過兩層的Nginx來實現(xiàn)多個Nginx的負(fù)載均衡墨林。LV5和F5是工作在網(wǎng)絡(luò)第四層的負(fù)載均衡解決方案,其中LVS是軟件犯祠,運行在操作系統(tǒng)內(nèi)核態(tài)旭等,可對TCP請求或更高層次的網(wǎng)絡(luò)協(xié)議進行轉(zhuǎn)發(fā),因此支持的協(xié)議更豐富衡载,并且性能也遠高于Nginx搔耕,可假設(shè)單機的LVS可支持幾十萬并發(fā)的請求轉(zhuǎn)發(fā);F5是一種負(fù)載均衡硬件月劈,與LVS提供的能力類似度迂,性能比LVS更高,但價格昂貴猜揪。由于LVS是單機版的軟件惭墓,若LVS所在服務(wù)器宕機則會導(dǎo)致整個系統(tǒng)無法訪問,因此需要有備用節(jié)點而姐±靶祝可使用keepalived軟件模擬出虛擬IP,然后把虛擬IP綁定到多態(tài)LVS服務(wù)器上,瀏覽器訪問虛擬IP時钧萍,會被路由器重定向到真實的LVS服務(wù)器褐缠,當(dāng)主LVS服務(wù)器宕機時,keepalived軟件會自動更新路由器中的路由表风瘦,把虛擬IP重定向到另外一臺正常的LVS服務(wù)器队魏,從而達到LVS服務(wù)器高可用的效果
第八次演進:通過DNS輪詢實現(xiàn)機房間的負(fù)載均衡
在DNS服務(wù)器中可配置一個域名對應(yīng)多個IP地址,每個IP地址對應(yīng)到不同的機房里的虛擬IP万搔。當(dāng)用戶訪問域名時胡桨,DNS服務(wù)器會使用輪詢策略或其他策略,來選擇某個IP供用戶訪問瞬雹。此方式能實現(xiàn)機房間的負(fù)載均衡昧谊,至此,系統(tǒng)可做到機房級別的水平擴展酗捌,千萬級到億級的并發(fā)量都可通過增加機房來解決呢诬,系統(tǒng)入口處的請求并發(fā)量不再是問題
隨著數(shù)據(jù)的豐富程度和業(yè)務(wù)的發(fā)展,檢索胖缤、分析等需求越來越豐富尚镰,單單依靠數(shù)據(jù)庫無法解決如此豐富的需求
第九次驗證:引入NoSQL數(shù)據(jù)庫和搜索引擎等技術(shù)
數(shù)據(jù)庫中的數(shù)據(jù)多到一定規(guī)模時,數(shù)據(jù)庫就不適用與復(fù)雜的查詢了草姻,往往只能滿足普通查詢的場景钓猬。對于統(tǒng)計報表場景稍刀,在數(shù)據(jù)量大時不一定能跑出結(jié)果撩独,而且在跑復(fù)雜查詢時會導(dǎo)致其他查詢變慢,對于全文檢索账月,可變數(shù)據(jù)結(jié)構(gòu)等場景综膀,數(shù)據(jù)庫天生不適用。因此需要針對特定場景局齿,引入合適的解決方案剧劝。如對海量文件存儲,可通過分布式文件系統(tǒng)HDFS解決抓歼,對于key-value類型的數(shù)據(jù)讥此,可通過HBase和Redis等方案解決,對于全文檢索場景谣妻,可通過搜索引擎如ElasticSearch解決萄喳,對于多維分析場景,可通過Kylin或Druid等方案解決蹋半。
引入更多組件同時會提高系統(tǒng)的復(fù)雜度他巨,不同的組件保存的數(shù)據(jù)需要同步,需要考慮一致性的問題,需要有更多的運維手段來管理這些組件等染突。
引入更多組件解決了豐富的需求捻爷,業(yè)務(wù)維度能夠極大擴充,隨之而來的是一個應(yīng)用中包含了太多的業(yè)務(wù)代碼份企,業(yè)務(wù)的升級迭代變得更困難
第十次演進:大應(yīng)用拆分為小應(yīng)用
按照業(yè)務(wù)模塊來劃分應(yīng)用也榄,使單個應(yīng)用的職責(zé)更清晰,相互之間可以做到獨立升級迭代司志。
這時應(yīng)用之間可能會涉及到一些公共配置手蝎,可以通過分布式配置中心Zookeeper來解決
不同應(yīng)用之間存在共用的模塊,由應(yīng)用單獨管理會導(dǎo)致相同代碼存在多份俐芯,導(dǎo)致公共功能升級時全部應(yīng)用代碼都要跟著升級
第十一次演進:復(fù)用的功能抽離成微服務(wù)器
如用戶管理棵介、訂單、支付吧史、鑒權(quán)等功能在多個應(yīng)用中都存在邮辽,那么可以把這些功能的代碼單獨抽取出來形成一個單獨的服務(wù)來管理,這樣的服務(wù)就是所謂的微服務(wù)贸营,應(yīng)用和服務(wù)之間通過HTTP吨述、TC或RPC請求等多種方式來訪問公共服務(wù),每個單獨的服務(wù)都可以由單獨的團隊來管理钞脂。
可以通過Dubbo揣云、SpringCloud等框架實現(xiàn)服務(wù)治理、限流冰啃、熔斷邓夕、降級等功能,提高服務(wù)的穩(wěn)定性和可用性
不同服務(wù)的接口訪問方式不同阎毅,應(yīng)用代碼需要適配多種訪問方式才能使用服務(wù)焚刚,此外,應(yīng)用訪問服務(wù)扇调,服務(wù)之間也可能互相訪問矿咕,調(diào)用鏈將會變得非常復(fù)雜,邏輯變得混亂狼钮。
第十二次演進:引入企業(yè)服務(wù)總線ESB屏蔽服務(wù)接口的訪問差異
通過ESB統(tǒng)一進行訪問協(xié)議轉(zhuǎn)換碳柱,應(yīng)用統(tǒng)一通過ESB來訪問后端服務(wù),服務(wù)與服務(wù)之間也通過ESB來互相調(diào)用熬芜,以此降低系統(tǒng)的耦合程度莲镣。這種單個應(yīng)用拆分為多個應(yīng)用,公共服務(wù)單獨抽取出來管理猛蔽,并使用企業(yè)消息總線來解除服務(wù)之間耦合問題的架構(gòu)剥悟,就是所謂的SOA(面向服務(wù))架構(gòu)灵寺。
業(yè)務(wù)不斷發(fā)展,應(yīng)用和服務(wù)都會不斷變多区岗,應(yīng)用和服務(wù)的部署變得復(fù)雜略板,同一臺服務(wù)器上部署多個服務(wù)還要解決運行環(huán)境沖突的問題,此外慈缔,對于如大促這類需要動態(tài)擴容的場景叮称,需要水平擴展服務(wù)的性能,就需要在新增的服務(wù)上準(zhǔn)備運行環(huán)境藐鹤,部署服務(wù)等瓤檐,運維將變得十分困難
第十三次演進:引入容器化技術(shù)實現(xiàn)運行環(huán)境隔離與動態(tài)服務(wù)管理
目前最流行的容器化技術(shù)是Docker,最流行的容器管理服務(wù)是Kubernetes(K8S)娱节,應(yīng)用/服務(wù)可以打包為Docker鏡像挠蛉,通過Kubernetes來動態(tài)分發(fā)和部署鏡像。Docker鏡像可以理解為一個能運行你的應(yīng)用/服務(wù)的最小的操作系統(tǒng)肄满,里面放著應(yīng)用/服務(wù)的運行代碼谴古,運行環(huán)境根據(jù)實際的需要設(shè)置好。把整個“操作系統(tǒng)”打包為一個鏡像后稠歉,就可以分發(fā)到需要部署相關(guān)服務(wù)的機器上掰担,直接啟動Docker鏡像就可以把服務(wù)起起來,使服務(wù)的部署和運維變得簡單怒炸。
使用容器化技術(shù)后服務(wù)動態(tài)擴容問題得以解決带饱,但機器還是需要公司自身來管理,在非大促的時候阅羹,還是需要閑置著大量的機器資源來應(yīng)對大促勺疼,機器自身成本和運維成本都極高,資源利用率地
第十四次演進:以云平臺承載系統(tǒng)
系統(tǒng)可部署到公有云上灯蝴,利用公有云的海量機器資源恢口,解決動態(tài)硬件資源的問題孝宗,在大促的時間段里穷躁,在云平臺中臨時申請更多的資源僻焚,結(jié)合Docker和K8S來快速部署服務(wù)雅倒,在大促結(jié)束后釋放資源隧魄,真正做到按需付費尽爆,資源利用率大大提高捡多,同時大大降低了運維成本公你。