"軟件開發沒有銀彈,咱們能作的就是選擇和平衡;"html
上一篇文章咱們聊了在單線程下程序優化的5個方向(ref:《程序優化的5個方向》);當單核優化到極值後,就到了多任務的狀況;
想起來很清晰,單個任務分解成多個任務,讓多個cpu同時來工做,並行執行,效率天然就上去了;
但,未必就這麼簡單;git
首先,咱們須要肯定,咱們的單個任務是否能夠分解;好比解析不少個文件,這樣的任務劃分紅多個很簡單;但若是是一個耗時的串行邏輯計算,後期的計算依賴前期的結果,這樣就很差拆分;這種形式可能須要在更高層次上來拆分;github
編程就是計算和數據;計算並行了,但數據仍是訪問同一份,訪問共同的資源會產生資源競爭;
若是不進行控制,可能致使同一份數據重複計算(多個讀的場景)或是髒數據的產生(有回寫的場景);數據庫
爲了讓數據訪問有序進行,須要引入鎖來防止髒數據;
控制鎖的粒度,是個須要精心考慮的話題;
好比對於大量讀少許寫的場景,相比一視同仁的加鎖,使用讀寫鎖能顯著提高效率;
咱們平常能接觸到的產品中,數據庫是個用鎖高手,在更新數據的時候,是鎖住行,仍是列、或是表,不一樣的粒度性能相差明顯;編程
考慮這樣的場景:多個線程都在等在一個鎖,若是能夠拿到鎖,線程就開始工做(線程池)
當鎖被釋放時,若是喚醒多個線程可能會產生 驚羣現象;
解決方案:
使用單線程方案/處理accpet鏈接 處理等待鎖的操做,讓任什麼時候刻只有一個線程在等待鎖;
更多細節參考:
《客戶-服務器程序設計方法》中 預先建立線程池,每一個線程各自accept 一節服務器
讓每一個線程使用本身的數據,讓數據不共有,這樣能去掉資源競爭,去掉鎖;
將數據複製爲多份,減小競爭,各自訪問各自的數據;
但這又引入了一個新的問題:若是各個線程回寫了數據,如何保證這麼數據的一致性?
畢竟它們表明的實際上是一份數據;架構
涉及到數據的一致性,多份數據之間的同步又是個難題;性能
那好,換個思路,不使用數據複製;咱們使用數據分片;分片這個思想更容易想到,既然「計算」被劃分爲多個小任務了,那麼數據也能夠一樣處理;
將數據分片,每份數據存的內容不相同,它們之間沒有共同點;
這樣,數據訪問沒有數據競爭,同時因爲數據不一樣,也不涉及到數據一致性同步的問題;
但,分片遠遠沒有想的那麼美好;
分片致使了每一個線程看到數據再也不是全集,而是片斷;這就註定了這個線程只能處理這部分的特定數據;這樣,線程之間的計算失去了可替換性;某種工做只能在特定的線程上處理;
而若是有個任務須要訪問全部的數據,這樣就變得更加複雜;
原來,分片以後,咱們將難題向上推了,推到線程層面,須要考慮到業務邏輯層面的處理;
這樣,可能更加複雜;優化
ok,想要速度更快,使用多核來處理,須要面對更多的問題;
將單機擴展多機集羣,涉及到架構層面來看,其實咱們的面對的問題是相似的;
參考:《大型網站技術架構》讀書筆記[2] - 架構的模式網站
軟件開發沒有銀彈,咱們能作的就是選擇和平衡;
Posted by: 大CC | 13AUG,2015
博客:blog.me115.com [訂閱]
Github:大CC