Tair: 淘寶的key/value解決方案

這篇文章由若海於2010年06月30日 17:16發表在Tair


今天我們對外開源了Tair,Tair是由淘寶開發的key/value解決方案,你可以在這裏獲取更多信息。

Tair在淘寶有着大規模的應用,在你登錄淘寶、查看商品詳情頁面、在淘江湖和好友“搗漿糊”等等時候,後面都在直接或間接的和Tair交互。

Tair是什麼

Tair是一個分佈式的key/value結構數據的解決方案,系統默認支持基於內存和文件的存儲引擎,對應於通常我們所說的緩存和持久化存儲。

Tair具有良好的架構,使得其在可擴展性、數據安全性方面都有較好的表現:

  • 基於對照表的靈活、良好的可擴展性
  • 輕量級的configserver
  • 抽象的存儲引擎層,支持添加新的存儲引擎
  • 自動的複製和遷移,對用戶透明
  • 多機架和多數據中心的支持
  • 插件容器

Tair除了基本的key/value操作外,還提供了一些實用的功能,使得其適用的場景更多:

  • 數據的version支持
  • 原子計數器支持
  • item支持 

對照表

Tair使用路由表來解決數據的路由問題。

簡單的路由表包含兩列,一列是hash值(我們通常稱其爲桶——bucket),一列是負責這個hash值的節點。比如:

0 192.168.10.1
1 192.168.10.2
2 192.168.10.1
3 192.168.10.2
4 192.168.10.1
5 192.168.10.2

這裏共6個桶,由兩臺機器負責,每臺機器負責3個桶。客戶端將key hash後,對6取模,找到負責的數據節點,然後和其直接通信。表的大小(行數)通常會遠大於集羣的節點數,這和consistent hash中的虛擬節點很相似。

這種結構使得Tair具有良好的可擴性,我們定義的好的可擴性是指我們投入多少機器,它們就能發揮其相應的作用。比如我們發現兩臺機器負載太高,我們可以選擇加入1臺,而不是通常的做法,將現有的節點數翻番。這種特性在這裏的優勢可能不是很明顯,假設集羣有1000臺,如果你擴容一定需要再加1000臺機器,那這種可擴性對我們來說是不夠好的。

假設我們加入了一臺新的機器——192.168.10.3,Tair會自動調整對照表,將部分桶交由新的節點負責,比如新的表很可能類似下表:

0 192.168.10.1
1 192.168.10.2
2 192.168.10.1
3 192.168.10.2
4 192.168.10.3
5 192.168.10.3

在老的表中,每個節點負責3個桶,當擴容後,每個節點將負責2個桶,數據被均衡的分佈到所有節點上。

如果有多個備份,那麼對照表將包含多列,比如備份是爲3,則表有4列,後面的3列都是數據存儲的節點。

輕量級的configserver

Tair的configserver用於維護集羣的可用節點,根據可用的節點,build數據分佈的對照表,Tair根據這張對照表決定數據的具體分佈。除此之外,configserver還負責管理遷移的進度等。

但和傳統集羣的中心節點不同,Tair的configserver是個輕量級的服務,並不會成爲集羣的瓶頸。

Tair用戶和configserver的交互主要是爲了獲取數據分佈的對照表,當client獲取到對照表後,會cache這張表,然後通過查這張表決定數據存儲的節點,所以請求不需要和configserver交互,這使得Tair對外的服務不依賴configserver,所以它不是傳統意義上的中心節點。

configserver維護的對照表有一個版本號,每次新生成表,該版本號都會增加。當有數據節點狀態發生變化(比如新增節點或者有節點不可用了)時,configserver會根據當前可用的節點重新生成對照表,並通過數據節點的心跳,將新表同步給數據節點。

當客戶端請求數據節點時,數據節點每次都會將自己的對照表的版本號放入response中返回給客戶端,客戶端接收到response後,會將數據節點返回的版本號和自己的版本號比較,如果不相同,則主動和configserver通信,請求新的對照表。

所以客戶端也不需要和configserver保持心跳,以便及時的更新對照表。這使得在正常的情況下,客戶端不需要和configserver通信,即使configserver不可用了,也不會對整個集羣的服務造成大的影響。

有了configserver,客戶端不需要配置數據節點列表,也不需要處理節點的的狀態變化,這使得Tair對最終用戶來說使用和配置都很簡單。

抽象的存儲引擎

Tair的存儲引擎有一個抽象層,只要滿足存儲引擎需要的接口,便可以很方便的替換Tair底層的存儲引擎。比如你可以很方便的將bdb、tc甚至MySQL作爲Tair的存儲引擎,而同時使用Tair的分佈方式、同步等特性。

Tair默認包含兩個存儲引擎:mdb和fdb。

mdb是一個高效的緩存存儲引擎,它有着和memcached類似的內存管理方式。但mdb支持使用share memory,這使得我們在重啓Tair數據節點的進程時不會導致數據的丟失,從而使升級對應用來說很平滑,不會導致命中率的波動。

fdb是一個簡單高效的持久化存儲引擎,使用樹的方式根據數據key的hash值索引數據,加快查找速度。索引文件和數據文件分離,儘量保持索引文件在內存中,以便減小IO開銷。使用空閒空間池管理被刪除的空間。

自動的複製和遷移

爲了增強數據的安全性,Tair支持配置數據的備份數。比如你可以配置備份數爲3,則每個數據都會寫在不同的3臺機器上。得益於抽象的存儲引擎層,無論是作爲cache的mdb,還是持久化的fdb,都支持可配的備份數。

當數據寫入一個節點(通常我們稱其爲主節點)後,主節點會根據對照表自動將數據寫入到其他備份節點,整個過程對用戶是透明的。

當有新節點加入或者有節點不可用時,configserver會根據當前可用的節點,重新build一張對照表。數據節點同步到新的對照表時,會自動將在新表中不由自己負責的數據遷移到新的目標節點。遷移完成後,客戶端可以從configserver同步到新的對照表,完成擴容或者容災過程。整個過程對用戶是透明的,服務不中斷。

多機架和多數據中心的支持

爲了更進一步的提高數據的安全性,Tair的configserver在build對照表的時候,可以配置考慮機房和機架信息。

比如你配置備份數爲3,集羣的節點分佈在兩個不同的機房A和B,則Tair會確保每個機房至少有一份數據。當A機房包含兩份數據時,Tair會確保這兩份數據會分佈在不同機架的節點上。這可以防止整個機房發生事故和某個機架發生故障的情況。

這裏提到的特性需要節點物理分佈的支持,當前是通過可配置的IP掩碼來區別不同機房和機架的節點。

插件容器

Tair還內置了一個插件容器,可以支持熱插拔插件。

插件由configserver配置,configserver會將插件配置同步給各個數據節點,數據節點會負責加載/卸載相應的插件。

插件分爲request和response兩類,可以分別在request和response時執行相應的操作,比如在put前檢查用戶的quota信息等。

插件容器也讓Tair在功能方便具有更好的靈活性。

功能支持

version

Tair中的每個數據都包含版本號,版本號在每次更新後都會遞增。這個特性可以幫助防止數據的併發更新導致的問題。

比如系統有一個value爲”a,b,c”,A和B同時get到這個value。A執行操作,在後面添加一個d,value爲”a,b,c,d”。B執行操作添加一個e,value爲”a,b,c,e”。如果不加控制,無論A和B誰先更新成功,它的更新都會被後到的更新覆蓋。

Tair無法解決這個問題,但是引入了version機制避免這樣的問題。還是拿剛纔的例子,A和B取到數據,假設版本號爲10,A先更新,更新成功後,value爲”a,b,c,d”,與此同時,版本號會變爲11。當B更新時,由於其基於的版本號是10,服務器會拒絕更新,從而避免A的更新被覆蓋。B可以選擇get新版本的value,然後在其基礎上修改,也可以選擇強行更新。

原子計數器支持

Tair從服務器端支持原子的計數器操作,這使得Tair成爲一個簡單易用的分佈式計數器。

item支持

Tair還支持將value視爲一個item數組,對value中的部分item進行操作。比如有個key的value爲[1,2,3,4,5],我們可以只獲取前兩個item,返回[1,2],也可以刪除第一個item。還支持將數據刪除,並返回被刪除的數據,通過這個接口可以實現一個原子的分佈式FIFO的隊列。

Tair的未來

我們將Tair開源,希望能有更多的用戶來使用、完善它,我們內部將不再有私有分支,所有的工作都將基於開源的分支進行,希望藉助社區的力量,使Tair有更寬廣的發展空間和更美好的未來。

發佈了77 篇原創文章 · 獲贊 3 · 訪問量 62萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章