国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > 優化推廣 > 正文

趙海平大神談異步處理對分布式系統的優化

2024-04-26 14:21:35
字體:
來源:轉載
供稿:網友

單機時代的數據請求

十五年前寫軟件是很簡單的,一個Client對應一個DB Server,或者多個Client對應一個DB Server,每一個Client執行各自的服務。當時的討論很多是說,這個東西要寫在Client端還是寫在DB Server端,流行的思路有兩種:

1.把DB Server寫得很復雜,比如Oracle數據庫,而Client端則寫得很簡單,只有調用返回
2.DB很簡單,只有簡單的表,而Client寫得復雜。很多創業公司會這樣做,因為他們對SQL不是很熟悉,但是很熟悉PHP。早期Facebook就是典型的代表


大數據時代的數據請求

單機時代隨著兩個趨勢而逐漸成為歷史。一個趨勢是隨著互聯網的流行,越來越多的人開始上網使用Web服務,而且很多時候用戶增長速度是非常快的,結果造成一臺DB Server無法儲存下所有用戶的數據。第二個趨勢是計算機能力越來越強,網絡服務針對每一個用戶要做的事情也變多了,比如Facebook不僅要保存一個用戶的個人信息,還有他的關系鏈信息,他的使用習慣、點擊習慣等,就造成一個用戶的數據量也大大增加,僅僅訪問一個DB Server就準備好一個頁面變成了不可能的事情。

這就帶來了一個問題:針對多個DB Server的程序應該怎么寫?

針對這個問題也有兩個思路:

1.串行同步。先query DB1,返回res1,再使用res1做另一個DB的query,返回res2。這是在第二個Query依賴第一個Query結果的情況
2.并行同步。針對DB1的query跟針對DB2的query同步進行。這是兩個Query之間沒有依賴關系的情況。Facebook早期專門寫了一個并行處理的函數,用法是 ExecParallelQuery(conn1,Query1,conn2,Query2)
這個時候的代碼就比以前的代碼更加復雜了,不過還是能實現需要實現的需求。但這時候帶來了一個新的問題,就是等待。一個頁面的加載可能需要調用不同的函數,而不同的函數可能是由不同的團隊寫的。比如獲取朋友關系的函數getFriends把自己需要的數據用同步的方式獲取了,但如果一個第三方開發者過來,則不僅要調用這個函數,還需要調用其他函數,這樣其他函數的執行就需要等待前面這個getFriends函數返回了結果之后才能開始執行,就很慢了。

要如何做到并行處理在代碼層面很直觀,在機器上的執行效率又好呢?

異步的處理思路就是這么來的。

所謂異步就是,我這個函數知道這里需要訪問哪幾個DB Server,但我先不著急去訪問,而是先記錄一下,等等看其他函數是不是也要訪問這個DB,如果有的話,待會兒再一起去訪問。異步處理的指令比如說是 conn.asyncExec(Query) ,這個可以立刻返回一個Future對象,意思就是“待會兒再去執行”。如果每個函數都返回這種Future對象,那么就可以根據這些Future對象來判斷哪些請求沒有依賴可以并行處理,哪些請求有依賴需要串行處理了。如此,不同的團隊寫出來的函數就不用一個等一個,而是可以在更高層面上互相合作。

然而這又帶來了一個問題,那就是異步處理的寫法是具有傳染性的。如果一個服務中有的函數寫的異步,有的函數沒寫異步,就會造成有的函數返回了Future Object,有的函數返回了數值,導致無法執行。要實現異步,需要關聯的所有函數都用異步的寫法返回Future Object才可以。

所以Facebook在轉向異步處理的過程是非常痛苦的,一開始做了局部修改,再修改調用了局部修改過的函數的函數,所有調用的調用都要修改,最后全部改成了異步,只要有調用遠程服務IO的操作都要改。每一個DB Query都拆分成兩步,一個set request,一個receive response。這里的工作量很大,所以如果創業團隊的話,最好是第一天就用正確的寫法,就不會這么痛苦。

所有函數改寫后,每一個函數執行都會返回Future Object。那么異步處理的第一步,就是將這些Future Object形成一棵依賴樹的結構,好像這樣:
201662104115662.jpg (602×332)

這里每個節點都是一個Future對象,每一個Future對象有兩種狀態,一個是等待執行,一個是完成執行。同級的節點是沒有依賴關系的,可以并行執行;上下節點是有依賴關系的,需要串行執行,先執行下層再執行上層。

樹結構形成后,從下到上執行,直到最上面的top parent節點被執行進入完成執行的狀態,就是完成,比如一個頁面加載完畢。

所以異步處理之后有一個很有意思的情況,那就是PHP這個語言已經跟以前不同了,不再是一上來就是執行,而是一上來先lazy一下,看清楚所有的Query之后再執行。

異步處理還需要解決的問題

到目前為止,這樣做異步處理似乎已經是足夠好的優化,但實際上還有問題。看看下面這個例子。

比如我們現在有兩個查詢需求。一個是查詢你在淘寶上買過東西的朋友,另一個是查詢你在淘寶上買過保時捷的朋友。常理來說,我們會先想到查詢你在淘寶上的朋友,再進行另一個條件的查詢,比如這樣:

Java Code復制內容到剪貼板
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 兰西县| 白朗县| 天祝| 从化市| 波密县| 安庆市| 科技| 乌鲁木齐市| 巴南区| 石屏县| 玛纳斯县| 临漳县| 阿城市| 东城区| 莎车县| 华宁县| 苍溪县| 明光市| 边坝县| 乌兰县| 灌南县| 保亭| 广昌县| 伊宁县| 怀柔区| 修水县| 夏津县| 额尔古纳市| 龙门县| 陆河县| 南昌市| 淮阳县| 米易县| 吉木乃县| 千阳县| 敦化市| 渝中区| 拜城县| 军事| 若羌县| 岑溪市|