天天看點

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

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

Tair是什麼

Tair是一個分布式的key/value結構資料的解決方案,系統預設支援基于記憶體和檔案的存儲引擎,對應于通常我們所說的緩存和持久化存儲。

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

  • 基于對照表的靈活、良好的可擴充性
  • 輕量級的configserver
  • 抽象的存儲引擎層,支援添加新的存儲引擎
  • 自動的複制和遷移,對使用者透明
  • 多機架和多資料中心的支援
  • 插件容器

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

  • 資料的version支援
  • 原子計數器支援
  • item支援 

對照表

Tair使用路由表來解決資料的路由問題。

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

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會自動調整對照表,将部分桶交由新的節點負責,比如新的表很可能類似下表:

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有更寬廣的發展空間和更美好的未來。

轉載于:https://www.cnblogs.com/yangchao/archive/2011/07/19/2125184.html