天天看點

Tair 分布式key/value存儲系統

Tair是由淘寶網自主開發的Key/Value結構資料存儲系統,在淘寶網有着大規模的應用。您在登入淘寶、檢視商品詳情頁面或者在淘江湖和好友“搗漿糊”的時候,都在直接或間接地和Tair互動。

Tair的功能

Tair是一個Key/Value結構資料的解決方案,它預設支援基于記憶體和檔案的兩種存儲方式,分别和我們通常所說的緩存和持久化存儲對應。

Tair除了普通Key/Value系統提供的功能,比如get、put、delete以及批量接口外,還有一些附加的實用功能,使得其有更廣的适用場景,包括:

  • Version支援>
  • 原子計數器
  • Item支援

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 分布式key/value存儲系統

圖 1 Tair整體架構圖

一個Tair叢集主要包括client、configserver和dataserver 3個子產品。Configserver通過和dataserver的心跳(HeartBeat)維護叢集中可用的節點,并根據可用的節點,建構資料的在叢集中的分布資訊(見下文的對照表)。Client在初始化時,從configserver處擷取資料的分布資訊,根據分布資訊和相應的dataserver互動完成使用者的請求。Dataserver負責資料的存儲,并按照configserver的訓示完成資料的複制和遷移工作。

資料的分布

分布式系統需要解決的一個重要問題便是決定資料在叢集中的分布政策,好的分布政策應該能将資料均衡地分布到所有節點上,并且還應該能适應叢集節點的變化。Tair采用的對照表方式較好地滿足了這兩點。

對照表的行數是一個固定值,這個固定值應該遠大于一個叢集的實體機器數,由于對照表是需要和每個使用Tair的用戶端同步的,是以不能太大,不然同步将帶來較大的開銷。我們在生産環境中的行數一般為1023 。

對照表簡介

下面我們看對照表是怎麼完成資料的分布功能的,為了友善,我們這裡假設對照表的行數為6。最簡單的對照表包含兩列,第一列為hash值,第二列為負責該hash值對應資料的dataserver節點資訊。比如我們有兩個節點192.168.10.1和192.168.10.2,那麼對照表類似:

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

當用戶端接收到請求後,将key的hash值和6取模,然後根據取模後的結果查找對照表。比如取模後的值為3,用戶端将和192.168.10.2通信。

對照表如何适應節點數量的變化

我們假設新增了一個節點——192.168.10.3,當configserver發現新增的節點後,會重新建構對照表。建構依據以下兩個原則:

1.資料在新表中均衡地分布到所有節點上。

2.盡可能地保持現有的對照關系。
           

更新之後的對照表如下所示:

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

這裡将原本由192.168.10.1負責的4和192.168.10.2負責的5交由新加入的節點192.168.10.3負責。

如果是節點不可用,則相當于上述過程反過來,道理是一樣的。

多備份的支援

Tair支援自定義的備份數,比如你可以設定資料備份為2,以提高資料的可靠性。對照表可以很友善地支援這個特性。我們以行數為6,兩個節點為例,2個備份的對照表類似:

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

第二列為主節點的資訊,第三列為輔節點資訊。在Tair中,用戶端的讀寫請求都是和主節點互動,是以如果一個節點不做主節點,那麼它就退化成單純的備份節點。是以,多備份的對照表在建構時需要盡可能保證各個節點作為主節點的個數相近。

當有節點不可用時,如果是輔節點,那麼configserver會重新為其指定一個輔節點,如果是持久化存儲,還将複制資料到新的輔節點上。如果是主節點,那麼configserver首先将輔節點提升為主節點,對外提供服務,并指定一個新的輔節點,確定資料的備份數。

多機架和多資料中心的支援

對照表在建構時,可以配置将資料的備份分散到不同機架或資料中心的節點上。Tair目前通過設定一個IP掩碼來判斷機器所屬的機架和資料中心資訊。

比如你配置備份數為3,叢集的節點分布在兩個不同的資料中心A和B,則Tair會確定每個機房至少有一份資料。假設A資料中心包含兩份資料時,Tair會盡可能将這兩份資料分布在不同機架的節點上。這可以減少整個資料中心或某個機架發生故障是資料丢失的風險。

輕量級的configserver

從Tair的整體架構圖上看,configserver很類似傳統分布式叢集中的中心節點。整個叢集服務都依賴于configserver的正常工作。

但Tair的configserver卻是一個輕量級的中心節點,在大部分時候,configserver不可用對叢集的服務是不造成影響的。

Tair使用者和configserver的互動主要是為了擷取資料分布的對照表,當client擷取到對照表後,會cache這張表,然後通過查這張表決定資料存儲的節點,是以請求不需要和configserver互動,這使得Tair對外的服務不依賴configserver,是以它不是傳統意義上的中心節點。

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

當用戶端請求資料節點時,資料節點每次都會将自己的對照表的版本号放入response中傳回給用戶端,用戶端接收到response後,會将資料節點傳回的版本号和自己的版本号比較,如果不相同,則主動和configserver通信,請求新的對照表。

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

僅有當configserver不可用,此時有用戶端需要初始化,那麼用戶端将取不到對照表資訊,這将使得用戶端無法正常工作。

DataServer内部結構

DataServer負責資料的實體存儲,并根據configserver建構的對照表完成資料的複制和遷移工作。DataServer具備抽象的存儲引擎層,可以很友善地添加新存儲引擎。DataServer還有一個插件容器,可以動态地加載/解除安裝插件。

Tair 分布式key/value存儲系統

圖 2 DataServer的内部結構示意圖

抽象的存儲引擎層

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配置,configserver會将插件配置同步給各個資料節點,資料節點會負責加載/解除安裝相應的插件。

插件分為request和response兩類,可以分别在request和response時執行相應的操作,比如在put前檢查使用者的quota資訊等。

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

Tair的未來

我們将Tair開源,希望有更多的使用者能從我們開發的産品中受益,更希望依托社群的力量,使Tair有更廣闊的發展空間。

Tair開源後,有很多使用者關心我們是否會持續維護這個項目。我們将Tair開源後,淘寶内部已經不再有私有的Tair分支,所有的開發和應用都基于開源分支。Tair在淘寶有非常廣的應用,我們内部有一個團隊,專門負責Tair的開發和維護,相信我們會和社群一起,将Tair越做越好。

有很多使用者在淘寶開源平台上申請加入Tair項目,加入項目在我們的開源平台上意味着成為

項目的送出者,可以向代碼庫直接送出代碼。是以我們暫時還沒有準許外部使用者加入,我們将在大家對Tair有更深入的了解後和社群一起決定是否準許加入項目的申請,在此之前,如果你有對代碼的改進,歡迎使用patch的方式送出給我們,我們将在review後決定是否合并到代碼庫。

文章摘自[https://www.oschina.net/p/tair?hmsr=aladdin1e1]

繼續閱讀