高并发,分布式系统要点
看到一篇不錯的文章,轉載不了就復制下來了,沒事可以看看。
現在很多高談闊論,高并發,大流量,分布式,SOA,名詞一大堆往往抓不住要點,對于熟悉的人來說,言之無味,而對不熟悉的人來說,更類似大師講法,除了增加神秘感外,讓人越發無從了解。
其實這些問題,本質是成本收益的平衡,嚴格說,這其實就是所謂技術最關注的問題,
正因為沒有銀彈,沒有統一的解決方案,所以任何系統都要結合業務自身特點,與軟件,硬件平衡一起考慮完整的解決方案。
可以從一個典型的電商平臺來分析,
假如,從無到有,有足夠人力時間,而且目標也非常明確,一個支持海量商家,海量用戶的,海量商品的平臺,應該怎么設計?
1.前端接入
只要高并發,即便全部是靜態頁面,哪怕只有一個文件,海量的并發連接也是必須首先解決的。
這個方案相對比較成熟,可以通過負載均衡,簡單增加web服務器,承載瀏覽器連接。單臺服務器nginx能承載的并發連接大致5000到數萬,
根據優化情況,可以簡單算出到底需要多少臺機器。在用戶使用瀏覽器的情況下,這里幾乎沒有取巧的地方。
如果不能接受則只能考慮專用客戶端,通過長鏈接,甚至UDP這類協議,來自己實現。
2.一旦請求全部接入了,就需要考慮處理問題
如果應用很單一,那么應用服務器就可以簡單擴展,類似接入的web服務器,單臺時間能處理的請求數,和單位時間總請求數,即可算出需要多少應用服務器,當然一般場景往往與用戶相關,這里最重要的就是要解決,應用服務器無狀態的問題,這樣才能無縫擴展,任何web接入的請求,可以隨便找一個空閑的應用服務器丟過去。
典型的,可以把用戶相關的信息保存到專門的狀態服務器中,請求時僅僅通過cookie提交一個令牌,用令牌從狀態服務器獲得對應用戶的信息。
狀態服務器,有一個天生的優勢,就是各個用戶數據之間往往隔離的,當單臺服務器抗不住時,簡單增加狀態服務器,而在應用服務器上簡單根據用戶id或令牌,計算出對應的狀態服務器即可。
狀態服務器可以充分利用各種NoSQL服務,比如典型的Redis,這里系統設計與業務需求就要綜合考慮了。
A 如果偶爾丟失狀態,可以接受,redis即可配置成不持久化。此時效率最高。
萬一狀態服務器掛了,應用端,簡單該向請求到新狀態服務器,用戶重新登錄即可,不會中斷太長服務。
B 如果希望盡量少的丟失狀態,那么redis就應該定期持久化,并做復制。
這樣某臺狀態服務器掛了,可以根據情況,選擇恢復主服務器,中斷一小段時間,數據最完整,或備用狀態服務器接管,快速恢復服務,數據可能多丟失一點點。
大部分用戶完全感知不到,個別用戶重新登錄即可。業務中斷也很小。
如果有可能,做成自動切換,會更高效率,但是一定要注意,不是什么都自動的好,如果沒有積累,你寫的程序,往往無法考慮大量意外,在“正常”的異常情況下可能切換很好,但是更多的異常情況下,有可能更糟糕。
C 如果要求絕對不能丟失狀態,允許中斷服務一段時間,redis可以配置成每次都持久化。持久化的硬盤也做冗余甚至做成共享存儲。
如果出問題,因為數據都沒有丟失,系統重啟或更換其他硬件,所有狀態即可恢復。但是顯然此時redis處理能力將大大減弱。
D 如果要求絕對不能丟失狀態,盡量減少中斷服務,
redis可以適當自己改造,將數據成功推送到備份服務器上,且備份服務器持久化之后,再返回成功。那么理論上,當主服務器掛掉,可以立刻切換到備份服務器上,而不丟失數據,用戶也基本感知不到變化。當然如何判斷主的掛掉,這里還是有大量陷阱,處理不好,反而更多的中斷服務。
如果去問一個不太了解技術的產品,這個用戶狀態到底什么要求,他很可能認為D是理所當然的,因為他完全沒有成本意識。
實際上對于大部分系統,A,B都是更佳的選擇,無論對于開發者,運維者,還是最終用戶。
A,B簡單,因此可靠,不容易出其他問題,開發成本低,運維成本低,最終更穩定,導致最終用戶更滿意。
只有用戶量足夠多,技術團隊,運維團隊足夠強,有能力實現更好的D,這時候D才是對產品來說更好的方案。
3.應用的拆分
到2,實際上解決了絕大多數系統的并發問題,因為可以簡單的通過增加硬件來擴容。
但是當應用原來越復雜之后,讓一個應用服務器包含所有的服務,是很困難的,從運維成本上考慮,必然有很大浪費,因為每個服務使用頻率不一樣。
一些,不太常用的服務,可能全部集中到兩臺服務器上就足夠了,這樣從其他大量服務器上將這些服務去掉,相當于整個系統節省大量內存。
而從開發角度,也必然是10個小項目每個10人維護,比100人維護一個大項目更容易,因此從開發角度也要求拆分應用。
拆分應用,雖然有些技術輔助手段,但實際主要還是依賴業務本身的分析,技術僅僅是輔助,比如解決各個應用系統之間數據同步問題,跨系統RPC問題等等。
而流行的SOA,則會努力將服務拆成更小而獨立的服務,一方面提高功能復用,另一方面便于開發維護,也方便運維管理。
但是這里有一個誤區,認為服務拆分得越小越好,其實,從理論上,服務怎么拆分,傳統的面向對象已經指明了方向,低耦合,高內聚,
說直白些,就是要善于封裝,面向對象從來不是類越多,方法越多越好。
所謂SOA治理,關鍵還是業務梳理!
4.持久化問題
如果說上面各種問題,目前技術都可以給出比較理想的解決方案,那么持久化瓶頸問題,卻始終是最大的問題所在。
前端接入服務器,應用服務器,都可以很好的橫向擴展,而狀態服務器,也因為其特殊性(持久化可以不太嚴格,數據之間無關聯),也可以比較好的橫向擴展。
而典型的聯機交易系統,總是要求數據一致性的,沒有產品會說偶爾用戶賬戶上少1分錢,是可以接受的。
傳統的銀行系統數據庫系統,會選擇更快的專有共享存儲,多機互備,將數據實實在在的寫到可靠存儲里,存儲通過raid方式來保證冗余防止單硬盤故障,
當主機故障時,無論軟硬件,簡單將共享存儲掛到備機上,來完成切換。
從安全角度,這種方案是非常高的,但是有兩個問題,一是價格昂貴,二是系統容量還是有限。
這種方案,其實就是目前大多數云平臺提供給中小系統的解決方案,只是用云存儲代替了傳統昂貴的共享存儲。
如果你的系統可以用云平臺的數據庫系統或者強勁單機來提供,其實這就是一個合理的好方案。無論你是租用云主機,還是自己弄個物理機。
但是如果系統規模足夠大,云平臺提供的單機無法滿足,或者其云數據庫也無法滿足(或者僅僅是因為價格太高),那么還是要想辦法自己來實現。
首先,存在這樣一個大數據庫類似傳統單機數據庫那樣,可以無限橫向擴展嗎?
在我看來是不存在的,因為傳統單機數據庫,重要的就是提供嚴格的事務支持,多機分布式事務,要想簡單橫向擴展,至少目前看來是很困難的。
CAP原則指出在一個分布式系統中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性),三者不可得兼。
而三者如何權衡,還是要依賴業務!而不是技術。
當然目前因為技術問題P是無法避免的,所以問題往往簡化成CA的選擇。
對于電商系統,從業務角度,A往往不能舍棄,而C則可以根據業務設計成最終一致性。
比如,購買業務,如果用戶賬戶錢一扣,他的訂單就應該是支付成功,單機上這點通過事務很容易實現,但是對于分布式系統,如果做這樣的要求,用戶未必高興,因為假設訂單系統出了些問題,訂單無法更新狀態,那么此時只能將用戶成功的支付也取消掉!
對于一個龐大的分布式系統,要保證每個系統都正常是不可能的,所以即便放棄A,允許任何一系統故障,整個系統暫停以保證數據一致性,從實際角度看也是不現實的。更不要說,參與系統越多分布協調成本越高,最終可能是即便所有系統都正常,其處理速度也完全無法接受了。
反之,如果支付成功了,允許訂單狀態暫時沒變,就可以等待訂單系統恢復后,再將其狀態修改為成功。通過業務設計,避免分布式事務,不光得到最大限度的A,也提高了整個系統的處理能力。 具體細節可參看《多數據源之間不使用分布式事務實現異步最終一致性》
用戶會不會容忍這個短暫的數據不一致呢?錢付了,訂單狀態卻沒立刻改。
會的,其實現實中他們經常這樣,以前去匯款時,自己的錢立刻交了出去,但是對方卻沒立刻收到,過幾天后,對方才收到,或者對方不在了,匯款再退回。
當然另外一些最終一致卻不會被接納,比如,如果存在一段時間,訂單先支付成功,用戶余額卻沒扣。
此時用戶即可用沒扣的余額去購買其他商品,這是系統巨大的漏洞。
所以一定是要和業務結合才能解決現實問題,也因此,在持久層這里,不要期望一個完整的分布式強數據一致性的系統,而應該學習現實世界的實現方式,分析業務,找到可以接受的最終數據一致性方案。
只要能接受最終數據一致性方案,那么就可以將存儲系統拆分成多個相對獨立的子系統,每個子系統內都是傳統的強一致性嚴格事務實現,而各個系統之間則通過相對松散的消息機制來互動。任何一個子系統都可以故障,操作可以在其他系統被cache,要么隨后恢復,要么超時取消。
其實很典型的例子就是第三方支付系統,每個系統都會對接,顯然這是兩個完全獨立的系統,甚至所有者也不同,但是對于支付業務的確很好的實現了,是一個真正意義上的分布式系統。
總結
對于一個電商平臺,可以大致描述一下其基礎架構,
1.一個接入的web集群,用來接入鏈接
2.一個狀態保存系統
3.拆分成多個相對獨立的應用系統,每個系統都無狀態,可橫向擴展。
4.根據應用和數據規模,將數據拆分成多個相對對立的存儲系統
可以是類似:用戶系統,訂單系統,支付系統這樣按功能拆分,
也可以再拆分成:用戶1系統,用戶2系統…這些系統功能完全一致,只是保存了不同用戶群的數據
其中每個存儲系統自己負責容錯,不同存儲系統通過應用系統通過內部消息來銜接,總是假定其他系統可能故障,也就必須考慮恢復或沖正。
這一切,尤其是3和4顯然更多依賴于業務的分析與設計,那么從技術角度,最終的系統就是一個完全分布式的系統,可以支持幾乎無限的擴展。
而某些技術,熱門中間件,框架,其實僅僅是一個技術手段,并沒有想象的那么重要。
轉載于:https://www.cnblogs.com/weiyi1314/p/7132314.html
總結
以上是生活随笔為你收集整理的高并发,分布式系统要点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 钉钉扫码登录的实现 与OAUTH2.0
- 下一篇: 关于SQLserver 的windows