《程序員》7月刊推薦:社交網數據庫技術分析

文 丁藝明

傳統互聯網正在邁向一個全新的時代——社交服務網(Social Networking Service)時代,從人與機器的時代邁向人與人的時代。互聯網社交服務網站的發展驗證了六度分隔理論Six Degrees of Separation),即人際關係脈絡方面你必然可以通過不超出六位中間人間接與世上任意先生女士相識。個體的社交圈會不斷地擴大和重疊並最終形成大的社交網絡。無論是國外的FacebookMySpaceTwitter,還是國內的開心網、人人網等都一頭扎進社交網,因爲他們認定社交網必然掀起新一輪的互聯網革命。

社交網的一個顯著特點是支持巨大用戶數,例如Facebook支持超過3億的用戶,其數據中心運行着超過萬臺的服務器,爲遍佈全球的用戶提供信息通訊服務。另外,任何兩個社交網用戶都可能交互,也就是必須支持任何兩個數據庫用戶的數據關聯操作。這對於服務端的數據庫管理提出了極大的挑戰。

 

關係數據庫與NoSQL 數據庫

關係數據庫使用者遵循一些數據庫範式,這些範式是數據庫設計中的一系列原理和技術,目的是爲了減少數據庫中數據冗餘和增進數據的一致性。結構化查詢語言SQL大量使用多表連接操作,SQL的通用性可以爲使用者帶來很多方便。

隨着越來越多大規模工作負荷應用的發行,對可伸縮性的需求,可能會變得非常迅速和無比龐大。

關係數據庫的確能伸縮自如,但通常只能在單臺服務器節點上進行。例如採用表分區技術,一個表格可以由多個物理文件組成,雖然表格的容量增大了,但該表格仍然只能由一數據庫引擎管理;另外增加一物理文件時,表格Schema得做改動,也就是還不能支持動態擴容。

一旦單節點的能力抵達上限,就得通過多服務器節點來擴展來分發負載。這時關係數據庫的複雜性就開始影響其潛在的擴展規模了。RDBMS支持分區視圖(Partition View) 技術,也就是支持聯邦數據庫(Federated Database)(如圖1)。一個分區視圖可以由多個分佈在不同數據庫節點服務器上的表格組合而成,數據庫用戶看到的只是該視圖,不必關心物理表格。通過數據水平分割技術,分區視圖把負載分擔到多個數據庫節點服務器上。擴容時,該方法除了需改動視圖定義外,分區視圖成爲分佈式數據庫系統的中心,存在單點故障問題。另外,跨數據庫節點之間多表格間連接操作的支持出現極大困難。

圖1  IBM聯邦數據庫的體系結構

圖1 IBM聯邦數據庫的體系結構

當試圖擴展數據庫系統到成百上千個節點時,將導致不堪複雜性之重負,這一特點使得RDBMS在大型分佈式系統平臺市場裏的生存能力被大幅削減。

爲了能向客戶提供一個伸縮自如的空間存放應用數據,供應商實際上只有一種真正的選擇——實現一種新型的專注於可擴展性的數據庫系統,而犧牲掉關係數據庫所帶來的其他好處。NoSQL是非關係型數據存儲的廣義定義,它打破了長久以來關係型數據庫與ACID理論大一統的局面。NoSQL數據存儲不需要固定的表結構,通常也不存在連接操作,在超大型數據存取上具備關係型數據庫無法比擬的性能優勢。該術語在2009 年初得到了廣泛認同,其中Key-Value數據模型是解決大型數據庫系統擴充問題的一種可行的解決方案。

 

Berkeley DB Key-Value數據模型

Berkeley DB是一種支持Key-Value數據模型的嵌入式數據庫存儲引擎。它不支持Client/Server網絡訪問方式,程序通過進程內的API訪問數據庫,不支持SQL或者其他數據庫查詢語言,不支持表結構和數據列。訪問數據庫的程序自主決定數據如何儲存在記錄裏,一條記錄由一個稱爲鍵(Key)的數據塊和一個稱爲值(Value)的數據塊組成。Berkeley DB不對記錄裏的數據進行任何包裝。應用程序可通過回調函數來定義不同鍵之間的大小關係,記錄和它的鍵都可以達到4GB的長度。儘管架構簡單,Berkeley DB卻支持很多高級的數據庫特性,比如ACID 數據庫事務處理、細粒度鎖、 XA接口、熱備份以及同步複製。Berkley DB爲不同用戶提供多種功能集(Feature Set):支持單個寫線程的數據存儲(Data Store);支持多併發寫線程的併發數據存儲(Concurrent Data Store);支持ACID和災難恢復的事務數據存儲(Transactional Data Store);通過複製支持容錯的高可靠數據存儲(High Availability)。

關係數據庫系統由存儲引擎和關係引擎兩個獨立部分組成。存儲引擎負責記錄存儲、索引和事務處理,關係引擎負責基於存儲引擎提供的服務,分析SQL、制定查詢執行計劃等。Berkeley DB是一種存儲引擎。例如MySQL數據庫可採用MyISAMInnoDBBerkeley DB等存儲引擎,如圖2所示。

圖2  MySQL使用的不同的存儲引擎

圖2 MySQL使用的不同的存儲引擎

Berkeley DB支持平衡樹(BTree)、哈希(Hash)、隊列(Queue)和記錄(Record)等數據集存儲和索引方式,還支持根據Key-Value中的Key創建集羣索引(Clustered Index)。這樣記錄集的物理次序就根據Key值大小來排列。如果要查詢結果記錄集的鍵值爲給定的一個範圍,該特性對於支持這種類型的快速查詢起了很大作用。Berkeley DB的一個Key-Value記錄集稱爲一個數據庫,會存儲在一個單獨文件中。Berkeley DB通過創建輔助數據庫(Secondary Database),允許對記錄集建立非集羣索引(Non-Clustered Index)。非集羣索引適用於快速查詢結果爲一條記錄,該記錄的鍵值爲給定的一個值。例如社交網用戶數據集:

User <UID, First_Name, Last_Name, Icon, E-mail>

如果以UID作爲主數據庫的鍵,其他字段作爲主數據庫的值,可再創建一個輔助數據庫,以E-mail作爲輔助數據庫的鍵,輔助數據庫的值爲E-mail所對應的UID,也就是指向主數據庫記錄的指針。若在一個Key-Value數據庫查詢,一般可根據查詢條件創建成一個鍵值,引擎返回一個遊標(Cursor),該遊標指向等於或大於該鍵值的結果數據集。

不難看出Berkeley DB使用的索引技術與SQL ServerOracle等高端數據庫系統是一樣的。RDBMS中經常使用的表格連接操作,在Berkeley DB 中不再支持,需要應用程序去實現兩個數據集的連接操作。這是Key-Value數據模型與關係數據模型典型的區別。

Berkeley DB 除了作爲MySQL的存儲引擎之外,還應用在OpenLDAPMemCache等知名軟件。

Berkeley DB類似的數據庫引擎還有Tokyo Cabinet/ Tyrant等。

 

社交網數據庫系統Cassandra

Facebook用戶數據集爲例,不可能把3億條數據集存放在同一個表格、文件或由同一臺計算機處理,這要求系統能支持數據分區,把數據集分割在多臺節點計算機中,每臺計算機分擔一部分負載,當用戶增加到一定程度時,系統能允許加入新的節點計算機,並且儘可能地減少數據遷移。

20071030日,AmazonCTO Werner Vogels發表了一篇文章,討論了一種基於Key-Value數據模型的存儲系統Dynamo。該系統支撐了不少Amazon的面向電子商務等關鍵性應用,它採用的存儲引擎是 Berkeley DB 事務數據存儲(Transactional Data Store)。Dynamo系統主要爲存儲1M左右甚至更小的內容,如購物車、推薦列表等。Dynamo設計上有下面一些特點。

  • 通過數據分區複製來支持高可靠性與高可伸縮性。
  • 始終可寫。
  • 一致性與寫入速度的折中,不要求同步寫入所有副本。
  • 對稱,完全去中心化,人工管理工作很小。

Cassandra DB最初由Facebook開發,後來轉變成爲開源項目。它是一個爲網絡社交雲計算設計的數據庫,主要特點是它不再是一個數據庫,而是由一堆數據庫節點共同構成的一個分佈式網絡服務,對Cassandra 的一個寫操作會被複制到其他節點上去,對Cassandra的讀操作也會被路由到某個節點上面去讀取。對於Cassandra羣集來說,擴展性能是比較簡單的事情,只管在羣集裏面添加節點就可以了。

Cassandra的用戶包括FacebookTwitterDigg等。Digg工程副總裁John Quinn說:“Cassandra採用完全分散的模式,每個節點都一樣,不會出現單點故障。它的容錯率也非常高,數據可以被複制到數據中心的多個節點中。它還非常具有彈性,隨着新設備的加入,其讀寫吞吐量將呈線性增加。

CassandraAmazon專有的完全分佈式的 Dynamo爲基礎,結合了Google BigTable基於列族(Column Family)的數據模型。P2P去中心化的存儲。很多方面都可以稱之爲Dynamo 2.0

3CassandraDynamoKey-Value之間的關係及在社交網上的應用。箭頭表示依賴關係。

圖3  Cassandra、Dynamo、Key-Value關係圖

圖3 Cassandra、Dynamo、Key-Value關係圖

分佈式存儲系統Dynamo

Dynamo採用Consistent Hashing算法來實現數據分區。

Consistent Hashing基本原理是:首先求出服務器節點的哈希值,並將其配置到02^32的圓上。然後用同樣的方法求出存儲數據的鍵的哈希值,並映射到圓上。再從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器上。如果超過2^32仍然找不到服務器,就會保存到第一臺服務器上。如圖4所示。

圖4 數據分割到4個節點數據庫

圖4 數據分割到4個節點數據庫

如果添加一臺服務器。只有在圓上,增加服務器的地點逆時針方向的第一臺服務器上的部分數據需要遷移到新的節點數據庫。如圖5所示。

圖5 添加Node5後需要遷移的數據

圖5 添加Node5後需要遷移的數據

數據分區後,數據塊被複制到N個節點上。複製時因爲更新產生的一致性問題的維護採取類似拜占庭容錯Quorum協議(Byzantine Fault-tolerance Quorum)的機制以及去中心化的複製同步協議。當一個存儲節點被認爲是拜占庭節點時,它的行爲可能任意偏移,表現在:拒絕響應請求、發送錯誤消息、存儲錯誤信息。Quorum協議中除了N之外還有兩個關鍵參數:RWR代表一次成功的讀取操作中最小參與節點數量,W代表一次成功的寫操作中最小參與節點數量。RW直接影響性能、一致性。和 值過小則影響一致性,過大則影響效率,這兩個值要平衡。如果W設置爲1,則一個實例中只要有一個節點可寫就寫成功,不會影響寫效率;如果R設置爲1,只要有一個節點可讀,就讀成功,不會影響讀效率。

 

Facebook數據庫查詢語言:FQL

Facebook爲開發者提供一套和SQL風格一致的數據庫查詢語言,稱爲Facebook Query LanguageFQL)。FQL是一種基於列的數據查詢語言。提供豐富的條件查詢,甚至包括子查詢。

例如,以下FQL查詢已安裝Facebook應用程序的用戶$app_user的好友ID集合:

SELECT uid FROM user WHERE is_app_user = 1 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = $app_user)

 

SQL重要區別是FQL不支持:

  • 多表連接:JOIN操作
  • 分組: GROUP BY操作
  • 排序:ORDER BY操作

隨着技術發展,一部分基於列結構的NoSQL數據庫開始支持分租、排序等複雜數據統計分析功能。

舉例:查詢好友信息

Facebook應用程序從以下兩個數據集中查找一用戶的好友數據集信息:

User <UID,First_Name, Last_Name, Icon>

Friend_List <UID, Friend_UID>

Friend_UID是一指向UserUID)的外鍵。RDBMS應用程序可使用數據集連接操作實現:

SELECT f.UID, u.Friend_UID, u.First_Name, u.Last_Name, u.Icon

FROM Friend_List f, User u

WHERE f.Friend_UID = u.UID AND

f.UID=@Input_UID

 

在社交網數據庫系統中,由於User數據分佈在多臺服務器中,其連接操作和外鍵約束實際上不能支持。

Facebook中查找一用戶的好友信息,得分AB兩步操作實現:

A步

SELECT Friend_UID

INTO @Out_Record_Set

FROM Friend_List f

WHERE f.UID=@Input_UID

 

B步

FOR EACH (Friend_UID in @Out_Record_Set)

SELECT u.Friend_UID, u.First_Name, u.Last_Name, u.Icon

FROM User u

WHERE u.UID = Friend_UID

 

No-SQL: Not Only SQL

對於那些關係複雜的數據處理和分析統計,SQL值得花錢。但當數據庫結構非常簡單時,SQL可能沒有太大用處。如果能用普通文件存儲代替數據庫系統的話,優選普通文件存儲。

對於社交網,能夠不受限制的擴展比更豐富的功能更加重要。建立大規模社交網成本的壓力讓很多社交網開發人員努力去尋找更高性價比的解決方案。研究表明基於普通廉價硬件的分佈式存儲解決方案比現在的高端數據庫更加可靠。支持SQLRDBMS不能解決所有問題的時候,NoSQL不是簡單的No SQL,其本質是Non-Relational,這時候NoSQL也就成爲Not Only SQL

 

原地址:http://www.programmer.com.cn/3711/

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