精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

當前位置:大數據業界動態 → 正文

QCon速遞:異步處理在分布式系統中的優化作用

責任編輯:editor006 作者:趙海平 |來源:企業網D1Net  2015-05-19 17:25:09 本文摘自:InfoQ

本文根據阿里巴巴技術保障研究員趙海平在2015年QCon全球軟件開發大會(北京站)主題演講整理而成。

趙海平在Facebook工作8年期間,主要針對后端進行性能優化的工作,包括PHP的優化,memcache的優化,等等后端組件。偶然有機會跟阿里的朋友溝通他們遇到的問題,聊得比較深入,就發現雖然阿里是用Java的,但在大的系統優化方面遇到的問題,跟Facebook是很類似的,因此回國加入阿里,希望幫助阿里把整個系統優化得更好。計劃第一步是先做整體的profiling系統,以找到性能的局部優化點;之后再進行一些大的架構優化,以及深入到JVM層面的優化。

回國跟很多人溝通,感覺現在到了2015年,國內的朋友們基本上也都對分布式系統的架構相當了解了。今天的演講就一個主題,就是分布式系統中異步處理的優化。

單機時代的數據請求

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

把DB Server寫得很復雜,比如Oracle數據庫,而Client端則寫得很簡單,只有調用返回

DB很簡單,只有簡單的表,而Client寫得復雜。很多創業公司會這樣做,因為他們對SQL不是很熟悉,但是很熟悉PHP。早期Facebook就是典型的代表

大數據時代的數據請求

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

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

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

串行同步。先query DB1,返回res1,再使用res1做另一個DB的query,返回res2。這是在第二個Query依賴第一個Query結果的情況

并行同步。針對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形成一棵依賴樹的結構,好像這樣:

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

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

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

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

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

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

IdList friends = waitFor(getFriends(myId));yield return getTaoBaoBuyers(friends);

但是對于保時捷這個查詢而言,這是不對的,因為淘寶上買保時捷的人是很少的,可能就一兩個,而淘寶上的好友數可能有上百。因此保時捷的查詢應該是這個次序比較優化:

IdList buyers = waitFor(getPorscheBuyer());yield return getFriends(buyers);

這個次序應該如何決定?實際上不應該在寫程序的時候決定,因為寫程序的時候是無法避免有先后順序的——編輯器只能一行一行的寫代碼,但是機器執行卻無需管這個。所以更好的方法應該是在執行代碼之前再加入一個phase。

其實傳統數據庫的cardinality(基數)功能已經解決了這個問題。你在DB query里面使用 INNER JOIN 這個指令,其實DB已經能夠預判哪一個表給出的row會比較少,從而以更優化的次序去執行。但現在我們用的編程語言,無論是 PHP,Java,Python還是C/C++,并沒有考慮這個問題。有人會開很多線程來解決這個問題,但這不是最佳方案,因為在Linux系統里,你的線程數要是上了200-300,就會有很大的overhead。

代碼執行的次序,這是一個。另外最近幾年還有一個流行的優化思路,就是上memcache。我們有時候會看到程序員把他自己的函數放進了memcache,相當于是依賴樹的中間的一個節點,我就問他為什么要把他這個Class放入memcache,他可能會說,他覺得這個節點和這個節點的child被調用的次數多。我覺得這可能不是特別理想的。你今天覺得這個Class被調用的多,可以放進memcache,但明天是不是會有更重要的Class會更值得放進 memcache,于是你又要把memcache的資源讓給這個新的Class?如果你放入memcache的Class并不是最重要的,這就相當于真正優化的可能性被拿走了。

如何讓異步執行的更好?

哪個query先執行,哪個query后執行,不應該是在編碼階段來做的。哪個Class該進memcache,哪個Class該出memcache,也不應該在編碼階段來做。應該有一個中間的階段,專門進行這種調度工作,然而到目前為止,還沒有公司能夠做到,因為沒有合適的語言。

異步處理在分布式系統中怎樣做有更好的優化作用,我們需要更多的思考。希望大家能夠把計算機當作科學去思考,而不僅僅是工程應用。我們現在看十幾年前,對單機是非常了解了,那么未來過了五年十年再回來看,可能對分布式系統也會了解的比現在更多很多,可能給分布式系統寫程序也會變得跟給單機寫程序一樣簡單。當然這就需要更合適的工具語言去給大家提供這種異步的便利。是不是會有Haskell那樣lazy的方式從系統層面解決這個問題?希望跟大家一起思考探討。

講師簡介

趙海平,阿里巴巴技術保障研究員,從小酷愛編程,多次獲得中學生計算機競賽的各種獎項,1987年以河北省高考狀元的優異成績進入北京大學生物系,又在美國紐約大學獲得分子生物學碩士,其后放棄博士學位,進入普林斯頓獲得計算機科學碩士,曾就職于微軟公司。2007年加入只有不到50個軟件工程師的 Facebook,致力于軟件性能和架構分析,在此期間創建了HipHop項目,重新編寫和實現PHP語言,使其速度提高5到6倍,為公司節約數十億美元。

HipHop 項目之后,致力于“用異步處理來優化分布式系統”的設計理念中,并為此做了多項分布式數據庫的優化研究,在PHP語言中加入了yield和 generator的新功能,來幫助日趨復雜的Facebook網頁設計。2015年3月回國,加入阿里巴巴技術保障部,將重點攻克阿里在軟件性能以及 Java使用過程中遇到的技術問題。

關鍵字:分布式系統IO串行處理

本文摘自:InfoQ

x QCon速遞:異步處理在分布式系統中的優化作用 掃一掃
分享本文到朋友圈
當前位置:大數據業界動態 → 正文

QCon速遞:異步處理在分布式系統中的優化作用

責任編輯:editor006 作者:趙海平 |來源:企業網D1Net  2015-05-19 17:25:09 本文摘自:InfoQ

本文根據阿里巴巴技術保障研究員趙海平在2015年QCon全球軟件開發大會(北京站)主題演講整理而成。

趙海平在Facebook工作8年期間,主要針對后端進行性能優化的工作,包括PHP的優化,memcache的優化,等等后端組件。偶然有機會跟阿里的朋友溝通他們遇到的問題,聊得比較深入,就發現雖然阿里是用Java的,但在大的系統優化方面遇到的問題,跟Facebook是很類似的,因此回國加入阿里,希望幫助阿里把整個系統優化得更好。計劃第一步是先做整體的profiling系統,以找到性能的局部優化點;之后再進行一些大的架構優化,以及深入到JVM層面的優化。

回國跟很多人溝通,感覺現在到了2015年,國內的朋友們基本上也都對分布式系統的架構相當了解了。今天的演講就一個主題,就是分布式系統中異步處理的優化。

單機時代的數據請求

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

把DB Server寫得很復雜,比如Oracle數據庫,而Client端則寫得很簡單,只有調用返回

DB很簡單,只有簡單的表,而Client寫得復雜。很多創業公司會這樣做,因為他們對SQL不是很熟悉,但是很熟悉PHP。早期Facebook就是典型的代表

大數據時代的數據請求

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

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

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

串行同步。先query DB1,返回res1,再使用res1做另一個DB的query,返回res2。這是在第二個Query依賴第一個Query結果的情況

并行同步。針對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形成一棵依賴樹的結構,好像這樣:

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

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

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

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

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

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

IdList friends = waitFor(getFriends(myId));yield return getTaoBaoBuyers(friends);

但是對于保時捷這個查詢而言,這是不對的,因為淘寶上買保時捷的人是很少的,可能就一兩個,而淘寶上的好友數可能有上百。因此保時捷的查詢應該是這個次序比較優化:

IdList buyers = waitFor(getPorscheBuyer());yield return getFriends(buyers);

這個次序應該如何決定?實際上不應該在寫程序的時候決定,因為寫程序的時候是無法避免有先后順序的——編輯器只能一行一行的寫代碼,但是機器執行卻無需管這個。所以更好的方法應該是在執行代碼之前再加入一個phase。

其實傳統數據庫的cardinality(基數)功能已經解決了這個問題。你在DB query里面使用 INNER JOIN 這個指令,其實DB已經能夠預判哪一個表給出的row會比較少,從而以更優化的次序去執行。但現在我們用的編程語言,無論是 PHP,Java,Python還是C/C++,并沒有考慮這個問題。有人會開很多線程來解決這個問題,但這不是最佳方案,因為在Linux系統里,你的線程數要是上了200-300,就會有很大的overhead。

代碼執行的次序,這是一個。另外最近幾年還有一個流行的優化思路,就是上memcache。我們有時候會看到程序員把他自己的函數放進了memcache,相當于是依賴樹的中間的一個節點,我就問他為什么要把他這個Class放入memcache,他可能會說,他覺得這個節點和這個節點的child被調用的次數多。我覺得這可能不是特別理想的。你今天覺得這個Class被調用的多,可以放進memcache,但明天是不是會有更重要的Class會更值得放進 memcache,于是你又要把memcache的資源讓給這個新的Class?如果你放入memcache的Class并不是最重要的,這就相當于真正優化的可能性被拿走了。

如何讓異步執行的更好?

哪個query先執行,哪個query后執行,不應該是在編碼階段來做的。哪個Class該進memcache,哪個Class該出memcache,也不應該在編碼階段來做。應該有一個中間的階段,專門進行這種調度工作,然而到目前為止,還沒有公司能夠做到,因為沒有合適的語言。

異步處理在分布式系統中怎樣做有更好的優化作用,我們需要更多的思考。希望大家能夠把計算機當作科學去思考,而不僅僅是工程應用。我們現在看十幾年前,對單機是非常了解了,那么未來過了五年十年再回來看,可能對分布式系統也會了解的比現在更多很多,可能給分布式系統寫程序也會變得跟給單機寫程序一樣簡單。當然這就需要更合適的工具語言去給大家提供這種異步的便利。是不是會有Haskell那樣lazy的方式從系統層面解決這個問題?希望跟大家一起思考探討。

講師簡介

趙海平,阿里巴巴技術保障研究員,從小酷愛編程,多次獲得中學生計算機競賽的各種獎項,1987年以河北省高考狀元的優異成績進入北京大學生物系,又在美國紐約大學獲得分子生物學碩士,其后放棄博士學位,進入普林斯頓獲得計算機科學碩士,曾就職于微軟公司。2007年加入只有不到50個軟件工程師的 Facebook,致力于軟件性能和架構分析,在此期間創建了HipHop項目,重新編寫和實現PHP語言,使其速度提高5到6倍,為公司節約數十億美元。

HipHop 項目之后,致力于“用異步處理來優化分布式系統”的設計理念中,并為此做了多項分布式數據庫的優化研究,在PHP語言中加入了yield和 generator的新功能,來幫助日趨復雜的Facebook網頁設計。2015年3月回國,加入阿里巴巴技術保障部,將重點攻克阿里在軟件性能以及 Java使用過程中遇到的技術問題。

關鍵字:分布式系統IO串行處理

本文摘自:InfoQ

電子周刊
回到頂部

關于我們聯系我們版權聲明隱私條款廣告服務友情鏈接投稿中心招賢納士

企業網版權所有 ©2010-2024 京ICP備09108050號-6 京公網安備 11010502049343號

^
  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 南京市| 思南县| 黑水县| 左贡县| 朝阳区| 莒南县| 营口市| 宜都市| 高雄县| 东海县| 连州市| 三亚市| 南丹县| 渑池县| 东海县| 新宾| 富源县| 临澧县| 郧西县| 广水市| 监利县| 枞阳县| 靖宇县| 虎林市| 凤庆县| 乌海市| 大竹县| 金塔县| 姜堰市| 龙江县| 常熟市| 五大连池市| 福泉市| 类乌齐县| 正定县| 资源县| 黄浦区| 商南县| 五华县| 鸡泽县| 涡阳县|