對于大部分應用來說,想要高性能,主要是要做到盡可能的減少網絡請求(含DB、Redis、MongoDB、MQ)等。幾乎所有的應用,性能瓶頸永遠是在帶寬那里;關于各個組件到CPU的時間周期,文字描述如下:L1>L2>memory>disk>internet。
大家都知道IP是逐跳協議,也就是說我只能從一個路由器,到下一個路由器,再到下一個路由器,如果你的電腦到服務器,中途要經過很多個路由器,那時間周期就會長很多很多很多。為什么要做CDN、P2P等也是這個考慮,縮短網絡的路徑(降低帶寬承載也是一方面)。
就像是我有一個游戲服務器,在線人數約4000,里面是一個狀態機在跑,需要不斷的去檢測各種狀態、經驗、星座、任務開放、技能開放等。一個玩家大約10個狀態的判定,4000個玩家必須在200ms之內檢測完畢,不然延遲會很嚴重,那1s就是大約執行5次,如果每一次數據都去Redis去取,大約是5*10*4000 = 200k次,別說Redis,再牛的服務器都頂不住!
遇到這種情況,建議把數據放在內存里面,直接從內存取,然后foreach。大部分的應用優化到這里,基本上應付所謂的日pv百萬,就不是什么問題了。
到了這一步,那么問題來了,對于內部應用,比如分布式文件存儲、數據分析、任務調度,咋整?
對于大數據,其實一直是一個偽命題,數據量太大屬于硬傷。所有的做大數據處理的,都是把數據分成小數據,然后分塊來處理,最后再合并。其實從MySQL、Oracle、msSQL等一系列人RMDB的分區,分庫上的處理就可以看出來。想要提高性能,必須要做到,每個模塊處理的數據量,都是細分到了一定粒度的。這個時候index、group、hash等的重要性,在這里就體現出來了。
若我有一個業務系統,每天的日志大約是10個G,一個月就大約是300G,一季度大約1T,我需要看每小時/每天/每周/每月/每季度的各種報表,每次都去數T里面去找,肯定是不可能的。
一般按業務分析每分鐘的數據,10G/24/60大約7M,然后生成一個分析后的結果文件,大約幾K,1小時就是60個文件,需要查看每小時的數據,則將60個文件的結果合并。
那我需要查看某一個用戶,最近10天來的所有操作/訂單,那原分組方式,已經無法滿足,這個時候怎么辦呢?
在插入用戶數據的時候,可以按照一定規則,比如用戶編號的后兩位取摸,去存儲在某一個文件里面,10G的數據,則可以相對平均的分配到100個文件里面去,需要查看某用戶時,則可以針對用戶編號取摸,直接定位到那個文件,然后再去里面查詢數據。這個是比較簡單的gourp+index。這一塊想明白以后,你就可以在這個基礎上面,寫個定制化的簡單的fs了
經常聽到有人說,多線程的程序還不如單線程的程序性能高。那如何編寫一個能合理利用CPU資源的多線程程序?
大家都知道,線程切換是需要額外的開銷,所以在編寫多線程程序的時候,就需要盡可能的避免共享式資源,這樣就可以在保證數據一致性的同時,而又避開線程等待的時間。
舉個簡單的例子:
我有個大的字典(Dictionary/Map)存放用戶的會話數據,每個線程,去這個字典里面去讀/寫數據的時候,都需要去上鎖,才能保證數據的一致性,如果兩個(更多)線程同時去讀/寫數據,其他的線程就需要去等待當前線程釋放資源,線程越多,則等待的幾率越大,性能則越差,多線程處理變成了單線程處理,且等待完了以后,能否再切換回來這個線程繼續執行,又是另外一個開銷,這一部分屬于系統拖托管,屬于不可控的。
那么問題來了:怎么解決呢?
根據硬件和實際測試數據,合理分配線程資源,比如,我初始化了8個線程,每個用戶的請求,對于線程總數取模,保證每個用戶的請求,同一個線程處理,則可以在每個線程內部,存放這些用戶數據,每個線程在自己內部進行存取,避開了lock,也避開了線程等待/切換帶來的資源開銷。不取模,隨機分配線程,然后用一個hash表來存放,也可。讓每個線程,專注于做自己的事情,任務調度作業,也是基于這個處理。把線程處理機制,放大到虛擬機/物理機之間的消息分發,也是如此。
總體來說,避開網絡開銷,避開海量數據,避開資源爭奪 是所有高性能的幾個基本要素。
-
cpu
+關注
關注
68文章
10854瀏覽量
211583 -
服務器
+關注
關注
12文章
9123瀏覽量
85324 -
路由器
+關注
關注
22文章
3728瀏覽量
113701 -
數據分析
+關注
關注
2文章
1445瀏覽量
34050
發布評論請先 登錄
相關推薦
評論