假設(shè)這是一個對外提供服務(wù)的大型分布式系統(tǒng),用戶連接到系統(tǒng),做一些操作,產(chǎn)生一些需要存儲的數(shù)據(jù),那么在這個過程中,會遇到哪些組件、理論與協(xié)議呢 用一個請求串起來用戶使用Web、APP、SDK,通過HTTP、TCP連接到系統(tǒng)。在分布式系統(tǒng)中,為了高并發(fā)、高可用,一般都是多個節(jié)點提供相同的服務(wù)。那么,第一個問題就是具體選擇哪個節(jié)點來提供服務(wù),這個就是負載均衡(load balance)。負載均衡的思想很簡單,但使用非常廣泛,在分布式系統(tǒng)、大型網(wǎng)站的方方面面都有使用,或者說,只要涉及到多個節(jié)點提供同質(zhì)的服務(wù),就需要負載均衡。 通過負載均衡找到一個節(jié)點,接下來就是真正處理用戶的請求,請求有可能簡單,也有可能很復(fù)雜。簡單的請求,比如讀取數(shù)據(jù),那么很可能是有緩存的,即分布式緩存,如果緩存沒有命中,那么需要去數(shù)據(jù)庫拉取數(shù)據(jù)。對于復(fù)雜的請求,可能會調(diào)用到系統(tǒng)中其他的服務(wù)。 承上,假設(shè)服務(wù)A需要調(diào)用服務(wù)B的服務(wù),首先兩個節(jié)點需要通信,網(wǎng)絡(luò)通信都是建立在TCP/IP協(xié)議的基礎(chǔ)上,但是,每個應(yīng)用都手寫socket是一件冗雜、低效的事情,因此需要應(yīng)用層的封裝,因此有了HTTP、FTP等各種應(yīng)用層協(xié)議。當系統(tǒng)愈加復(fù)雜,提供大量的http接口也是一件困難的事情。因此,有了更進一步的抽象,那就是RPC(remote produce call),是的遠程調(diào)用就跟本地過程調(diào)用一樣方便,屏蔽了網(wǎng)絡(luò)通信等諸多細節(jié),增加新的接口也更加方便。 一個請求可能包含諸多操作,即在服務(wù)A上做一些操作,然后在服務(wù)B上做另一些操作。比如簡化版的網(wǎng)絡(luò)購物,在訂單服務(wù)上發(fā)貨,在賬戶服務(wù)上扣款。這兩個操作需要保證原子性,要么都成功,要么都不操作。這就涉及到分布式事務(wù)的問題,分布式事務(wù)是從應(yīng)用層面保證一致性:某種守恒關(guān)系。 上面說道一個請求包含多個操作,其實就是涉及到多個服務(wù),分布式系統(tǒng)中有大量的服務(wù),每個服務(wù)又是多個節(jié)點組成。那么一個服務(wù)怎么找到另一個服務(wù)(的某個節(jié)點呢)?通信是需要地址的,怎么獲取這個地址,最簡單的辦法就是配置文件寫死,或者寫入到數(shù)據(jù)庫,但這些方法在節(jié)點數(shù)據(jù)巨大、節(jié)點動態(tài)增刪的時候都不大方便,這個時候就需要服務(wù)注冊與發(fā)現(xiàn):提供服務(wù)的節(jié)點向一個協(xié)調(diào)中心注冊自己的地址,使用服務(wù)的節(jié)點去協(xié)調(diào)中心拉取地址。 從上可以看見,協(xié)調(diào)中心提供了中心化的服務(wù):以一組節(jié)點提供類似單點的服務(wù),使用非常廣泛,比如命令服務(wù)、分布式鎖。協(xié)調(diào)中心最出名的就是chubby,zookeeper。 回到用戶請求這個點,請求操作會產(chǎn)生一些數(shù)據(jù)、日志,通常為信息,其他一些系統(tǒng)可能會對這些消息感興趣,比如個性化推薦、監(jiān)控等,這里就抽象出了兩個概念,消息的生產(chǎn)者與消費者。那么生產(chǎn)者怎么講消息發(fā)送給消費者呢,RPC并不是一個很好的選擇,因為RPC肯定得指定消息發(fā)給誰,但實際的情況是生產(chǎn)者并不清楚、也不關(guān)心誰會消費這個消息,這個時候消息隊列就出馬了。簡單來說,生產(chǎn)者只用往消息隊列里面發(fā)就行了,隊列會將消息按主題(topic)分發(fā)給關(guān)注這個主題的消費者。消息隊列起到了異步處理、應(yīng)用解耦的作用。 上面提到,用戶操作會產(chǎn)生一些數(shù)據(jù),這些數(shù)據(jù)忠實記錄了用戶的操作習慣、喜好,是各行各業(yè)最寶貴的財富。比如各種推薦、廣告投放、自動識別。這就催生了分布式計算平臺,比如Hadoop,Storm等,用來處理這些海量的數(shù)據(jù)。 最后,用戶的操作完成之后,用戶的數(shù)據(jù)需要持久化,但數(shù)據(jù)量很大,大到按個節(jié)點無法存儲,那么這個時候就需要分布式存儲:將數(shù)據(jù)進行劃分放在不同的節(jié)點上,同時,為了防止數(shù)據(jù)的丟失,每一份數(shù)據(jù)會保存多分。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫是單點存儲,為了在應(yīng)用層透明的情況下分庫分表,會引用額外的代理層。而對于NoSql,一般天然支持分布式。 |
|