海量數據下的分佈式存儲與計算

親,轉載請保留以下信息

@from  : http://blog.csdn.net/larrylgq/article/details/7851207

@author :呂桂強

@email; [email protected]


存儲

從理論角度

提到大數據存儲nosql是不得不提的一個部分,CAP,BASE,ACID這些原理在過去的一些年對其有着一定的指導作用(近年來隨着各種實時計算模型的發展,CAP也被漸漸打破)

CAP:(Consistency-Availability-Partition Tolerance
數據一致性(C): 等同於所有節點訪問同一份最新的數據副本;
對數據更新具備高可用性(A): 在可寫的時候可讀, 可讀的時候可寫,最少的停工時間
能容忍網絡分區(P)
eg:
傳統數據庫一般採用CA即強一致性和高可用性
nosql,雲存儲等一般採用降低一致性的代價來獲得另外2個因素


ACID:按照CAP分法ACID是許多CA型關係數據庫多采用的原則:
A:Atomicity原子性,事務作爲最小單位,要麼不執行要麼完全執行
C:Consistency一致性,一個事務把一個對象從一個合法狀態轉到另一個合法狀態,如果交易失敗,把對象恢復到前一個合法狀態。即在事務開始之前和事務結束以後,數據庫的完整性約束沒有被破壞
I:Isolation獨立性(隔離性),事務的執行是互不干擾的,一個事務不可能看到其他事務運行時,中間某一時刻的數據。
D:Durability:事務完成以後,該事務所對數據庫所作的更改便持久的保存在數據庫之中,並不會被回滾


BASE:一般是通過犧牲強一致性,來換取可用性和分佈式
BA:Basically Aavilable基本可用:允許偶爾的失敗,只要保證絕大多數情況下系統可用
S:Soft State軟狀態:無連接?無狀態?
E:Eventual Consistency最終一致性:要求數據在一定的時間內達到一致性
以雲存儲爲例:目前的雲存儲多以整體上採用BASE局部採用ACID,由於使用分佈式使用多備份所以多采用最終一致性


Nosql常見的數據模型有key/value和Schema Free(自由列表模式)兩種,
key/value,每條記錄由2個域組成,一個作爲主鍵,一個存儲記錄的數據(mongodb)
Schema Free, 每條記錄有一個主鍵,若干條列組成,有點類似關係型數據庫(hbase)


在實現這些模型的時候基本使用2種實現方式:哈希加鏈表,或者B+樹的方式


哈希加鏈表:通過將key進行哈希來確定存儲位置,相同哈希值的數據存儲成鏈表




基本的hash尋址算法有除法散列法,平方散列法,斐波那契(Fibonacci)散列法等,但是java是這樣做的


static int indexFor(int h, int length) {  
       return h & (length-1);  
   }  
java會用key的hashcode值與數組的槽數-1進行與運算
這裏會有一個問題只有當數組的槽數爲2的n次方-1,其二進制全是1的(如2的2次方-1=11)的時候哈希值產生碰撞的概率是最小的
所以在java中hashmap的數組的初始大小是16(2的4次方)


hashmap的問題


hashmap的resize:
當不斷put數據使數據慢慢變大的時候,剛開始的數組已經不能滿足需求了,我們需要擴大數組的槽數
hashmap中有loadFactor屬性,該屬性默認爲0.75,即元素個數達到數組的百分之七十五的時候,數組槽數會進行翻倍,並且之前已存入的數據會重新進行計算。
 
so:如果我們可以預估我們會在hashmap中存放1000個數據,那麼我們就要確保數組的槽數乘上0.75大於1000,我們得到1366,如果我們這樣寫new HashMap(1366),java會自動幫我們轉換成new HashMap(2048)(2的n次方)


B+樹:B+樹的特點


1.節點中關鍵字數量與字節點數相同。  
2.所有葉子結點中包含全部指向記錄的指針
3.葉子結點按照自小而大順序鏈接
5通常在B+樹上有兩個頭指針,一個指向根結點,一個指向關鍵字最小的葉子結點
(爬蟲會有深度優先,廣度優先的算法)



來自百度的圖



so:hash查找單條非常快
b+樹,範圍查找很快(深度優先,廣度優先的遍歷等)



需要一個可以排序的hash結構


空間換時間:跳錶+hashtable實現可排序的hash


跳錶結構


so:增,刪,改(通過跳錶)的複雜度爲o(log(n))
查(通過hashtable)的複雜度爲O(1)



當然我們不知道有結構化的數據,特別我們存儲的數據是需要拿來進行復雜的數據挖掘算法,所以有的時候nosql並不能滿足我們的需要

實際的數據

結構化
半結構化(我們的數據)
非結構化
海量(百T級別)
數據偶爾丟掉幾條沒關係
數據質量差


選擇hdfs的原因


hdfs在設計之初考慮到了以下幾個方面:
1,hdfs將採用大量穩定性差的廉價pc來做爲文件存儲設備,所以pc發生死機或硬盤故障的機率極高,應看作是常態,所以hdfs應該提供數據多備份,自動檢測節點存活,和故障機器的自動修復
2,hdfs存儲的大多是大文件,所以針對大文件的讀寫會作出優化
3,對於寫入數據來說,系統會有很多追加操作,而很少會有隨機讀寫
4,對於讀取數據來說,大多數的操作是順序讀,很少有隨機讀


計算

從理論角度

離線計算      :針對海量的,對實時性要求不是很高的數據
實時流計算  :數據清洗,topn等應用場景
列存儲 :大表jion,海量數據實時查找
key-value :對半結構化,非結構化數據的實時查找(結構靈活,適合項目初期的試錯階段)

內存和磁盤計算的區別


尋址
內存是通過電子工作的,所以搜索速度和物理結構無關,進行尋址時只需要微秒級別既可以
磁盤在尋址時需要1,移動磁頭2,旋轉磁盤  因爲磁盤旋轉的速度有限,所以尋址消耗毫秒別時間
*操作系統會將一個連續的數據存放在一起(win一般是4KB),這樣磁盤旋轉一週讀取的數據就會多些,從而提高效率


傳輸速度
內存和硬盤的數據都會被讀到cpu的緩存中,但是從內存到緩存和從硬盤到緩存的傳輸速度是差別很大的
內存到緩存的速度大概有7-8GB/秒,而磁盤到緩存的速度大概只有60MB/秒


so:因此內存計算和磁盤計算的速度差可以達到百萬倍以上


離線計算

hadoop現了mapreduce的思想,將數據切片計算來處理大量的離線數據數據。

hadoop處理的數據必須是已經存放在支持的分佈式文件系統上或者類似hbase的數據庫中,所以hadoop實現的時候是通過移動計算到這些存放數據的機器上來提高效率

ps:針對hadoop我們的使用是開發一個類似pig的mdx框架,與pig的區別是我們的框架會更加的針對業務友好,業務人員只需要瞭解維度信息和需要的度量即可


實時流計算

storm是一個流計算框架,處理的數據是實時消息隊列中的,所以需要我們寫好一個topology邏輯放在那,接收進來的數據來處理,所以是通過移動數據平均分配到機器資源來獲得高效率


列存儲

提出region和Xfile概念(如hbase的HFILE和hive的rcfile以及yuntable的YFile)
根據key將數據分到不同的region,保存log,數據壓縮並行列轉置後存到Xfile,定期或使用內存到了一定闕值flash到硬盤


列存優點舉例-

eg1:通過region和XFile過濾掉大量數據,如果對100g的數據做分析

通過region會過濾掉一大批數據
對於數值類型,每個xfile會有一個預統計(最大最小值)又會過濾掉一部分數據
假設還剩下2.5g的數據
對於頻繁使用的數據會在內存中有緩存
假設命中2g
剩下的0.5g會已壓縮的方式存放在硬盤(定長字段壓縮比更大,當然數字的壓縮比最大)
so-100g的查詢=》2g的內存查找+0.5g的硬盤查找(內存尋址是硬盤尋址的幾百萬倍)

eg2:通過動態擴展列來進行大表的jion

google的bigtable進行cookie的join,是將一個幾千萬的用戶行爲的表jion到一張100億行的cookie大表,它只需要將新的表根據cookie重新做一下索引即可,因爲數據是列存儲所以具體的數據存儲不需要實際的硬盤移動,大大減少了jion的時間,儘管這個表有幾十萬的列但對查找幾乎是沒有影響的

key-value

存儲非結構化數據

-eg:評論,問答


再看下數據

結構化
半結構化(我們的數據)
非結構化
海量(百T級別)
數據偶爾丟掉幾條沒關係
數據質量差


到目前爲止我們的處理方案是:


離線分析(對實時性要求不高-hadoop)-結構化,半結構化,非結構化
實時分析(對實時性要求極高-storm)-結構化,半結構化,非結構化
實時查找(經常性對大量數據進行count等操作-infobright,hbase)-結構化,部分支持半結構化

有時我們需要對非結構化的數據做一些實時搜索的功能keyvalue搞不定怎麼辦--實時搜索(巧妙設計數據結構)

我們的做法是:

倒排索引

+關鍵字的前綴冗餘

具體關鍵字的前綴冗餘使用redis的zset完成,其本質也是一個hashtable+跳錶的所以結構

這樣存的時候需要切詞,存儲,key和關鍵字映射的存儲,前綴和關鍵字映射的存儲

但是讀的時候是非常迅速的,如下圖當用戶輸入J 就可以很快的找到關於java等的信息(當然還需要一些評分,權重算法)



服務架構需要考慮的問題:


CPU負載和I/O負載(計算密集型和io密集型)

CPU負載-計算密集型

所謂CPU負載就是通常的web服務等,這些服務基本上只消耗cpu,所以只要增加安裝相同服務的服務器,然後就可已通過負載均衡器工作了


I/O負載-io密集型


1.數據的切割和在機器間的分配策略(原則是儘量移動計算而不是移動數據)
2.如何通過多備份來確保數據的可用性(確保多備份的一致性)
3.如何使集羣針對性強的響應客戶端的讀寫請求
4.如何實現集羣中單臺機器的熱拔插
5.好的負載均衡策略
6.網絡通信延遲,因爲計算機運行的速度是微秒甚至納秒,所以毫秒級別的延遲對程序來說性能損害是極大的


ps:我們平常使用的路由器一般pps(每秒轉發數爲幾十萬左右),所以一般的千兆以太網的極限就在幾十萬/秒
除此之外由於正常的路由器的ARP表上限爲900左右
兩個原因導致一個子網中機器不能過多,當集羣中機器過多時就需要進行網絡的層次話


虛擬化優點

1,擴展性-可以動態的遷移和複製,使得服務器增加變得更簡單
2,提高資源利用率
3,降低運維成本(遠程管理,環境更單一
異常行爲局部化,使得主機控制更簡單)
4,提高可用性(抽象硬件差異)
5,  調整負載(軟件層面對負載進行控制,當監測到負載消耗異常可重啓進程或者虛擬機)

缺點

1,虛擬機本身的損耗(cpu,內存)
2,網絡性能損耗近一半
3,I/O性能略微降低0.5%左右




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章