深入理解tair

轉:https://www.jianshu.com/p/ccb17daed766

 

tair是什麼?

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

Tair於2010年6月30號在淘寶開源平臺上正式對外開源。

Tair有四種引擎:mdb, rdb, kdb和ldb。分別基於四種開源的key/value數據庫:memcached, Redis, Kyoto Cabinet和leveldb。Tair可以讓你更方便地使用這些KV數據庫。比如Redis沒有提供sharding操作,如果有多個Redis Server,你需要自己寫代碼實現sharding,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成爲一個簡單易用的分佈式計數器。

Tair有以下優點:

  1. 統一的API。無論底層使用何種引擎,上層的API是一樣的。

  2. Tair將集羣操作封裝起來,解放了開發者。淘寶內部在使用Tair時,一般都是雙機房雙集羣容錯,利用invalid server保證兩個集羣間的一致性,這些對於開發者都是透明的。

Item支持

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

使用場景?

  1. 非持久化(mdb,rdb)

數據可以以key/value的形式存儲
數據可以接受丟失
訪問速度要求很高
單個數據大小不是很大,一般在KB級別
數據量很大,並且有較大的增長可能性
數據更新不頻繁

  1. 持久化(kdb,ldb)

數據可以以key/value的形式存儲
數據需要持久化
單個數據大小不是很大,一般在KB級別
數據量很大,並且有較大的增長可能性
數據的讀寫比例較高

如何實現的?

Tair是Master/Slave結構。Config Server管理Data Server節點、維護Data Server的狀態信息;Data Server負責數據存儲,按照Config Server的指示完成數據複製和遷移工作,並定時給Config Server發送心跳信息。Config Server是單點,採用一主一備的方式保證可靠性。

tair網絡拓撲

tair架構

數據的分佈問題

分佈式系統需要解決的一個重要問題便是決定數據在集羣中的分佈策略,好的分佈策略應該能將數據均衡地分佈到所有節點上,並且還應該能適應集羣節點的變化。Tair採用的對照表方式較好地滿足了這兩點。

對照表的行數是一個固定值,這個固定值應該遠大於一個集羣的物理機器數,由於對照表是需要和每個使用Tair的客戶端同步的,所以不能太大,不然同步將帶來較大的開銷。我們在生產環境中的行數一般爲1023 。

對照表簡介

下面我們看對照表是怎麼完成數據的分佈功能的,爲了方便,我們這裏假設對照表的行數爲6。最簡單的對照表包含兩列,第一列爲hash值,第二列爲負責該 hash值對應數據的dataserver節點信息。比如我們有兩個節點192.168.10.1和192.168.10.2,那麼對照表類似:
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

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

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

  1. 數據在新表中均衡地分佈到所有節點上。
  2. 儘可能地保持現有的對照關係。

多備份的支持

Tair支持自定義的備份數,比如你可以設置數據備份爲2,以提高數據的可靠性。對照表可以很方便地支持這個特性。我們以行數爲6,兩個節點爲例,2個備份的對照表類似:
0 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還有一個插件容器,可以動態地加載/卸載插件。

 

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 的分佈採用的是一致性哈希算法, 對於所有的key,分到Q個桶中, 桶是負載均衡和數據遷移的基本單位。 config server 根據一定的策略把每個桶指派到不同的data server上。 因爲數據按照key做hash算法, 所以可以認爲每個桶中的數據基本是平衡的. 保證了桶分佈的均衡性, 就保證了數據分佈的均衡性。

增加或者減少data server的時候會發生什麼

當有某臺data server故障不可用的時候, config server會發現這個情況, config server負責重新計算一張新的桶在data server上的分佈表, 將原來由故障機器服務的桶的訪問重新指派到其它的data server中。這個時候, 可能會發生數據的遷移。比如原來由data server A負責的桶,在新表中需要由 B負責。而B上並沒有該桶的數據, 那麼就將數據遷移到B上來。同時config server會發現哪些桶的備份數目減少了, 然後根據負載情況在負載較低的data server上增加這些桶的備份。當系統增加data server的時候, config server根據負載,協調data server將他們控制的部分桶遷移到新的data server上。遷移完成後調整路由。當然系統中可能出現減少了某些data server 同時增加另外的一些data server。處理原理同上。 每次路由的變更,config server都會將新的配置信息推給data server。在客戶端訪問data server的時候, 會發送客戶端緩存的路由表的版本號。如果data server發現客戶端的版本號過舊,則會通知客戶端去config server取一次新的路由表。如果客戶端訪問某臺data server 發生了不可達的情況(該 data server可能宕機了),客戶端會主動去config server取新的路由表。

發生遷移的時候data server如何對外提供服務

當遷移發生的時候, 我們舉個例子, 假設data server A 要把桶 3,4,5 遷移給data server B。因爲遷移完成前,客戶端的路由表沒有變化,客戶端對 3, 4, 5 的訪問請求都會路由到A。現在假設 3還沒遷移, 4 正在遷移中, 5已經遷移完成。那麼如果是對3的訪問, 則沒什麼特別, 跟以前一樣。如果是對5的訪問, 則A會把該請求轉發給B,並且將B的返回結果返回給客戶,如果是對4的訪問,在A處理,同時如果是對4的修改操作會記錄修改log。當桶4遷移完成的時候,還要把log發送到B,在B上應用這些log。最終A B上對於桶4來說, 數據完全一致纔是真正的遷移完成。當然如果是因爲某data server宕機而引發的遷移, 客戶端會收到一張中間臨時狀態的分配表。這張表中,把宕機的data server所負責的桶臨時指派給有其備份data server來處理。 這個時候服務是可用的,但是負載可能不均衡。當遷移完成之後,才能重新達到一個新的負載均衡的狀態。

桶在data server上分佈時候的策略

程序提供了兩種生成分配表的策略, 一種叫做負載均衡優先, 一種叫做位置安全優先: 我們先看負載優先策略。當採用負載優先策略的時候,config server會盡量的把桶均勻的分佈到各個data server上。 所謂儘量是指在不違背下面的原則的條件下儘量負載均衡。

1、每個桶必須有COPY_COUNT份數據

2、一個桶的各份數據不能在同一臺主機上

位置安全優先原則是說, 在不違背上面兩個原則的條件下, 還要滿足位置安全條件,然後再考慮負載均衡。 位置信息的獲取是通過 _pos_mask(參見安裝部署文檔中關於配置項的解釋) 計算得到。一般我們通過控制 _pos_mask 來使得不同的機房具有不同的位置信息。 那麼在位置安全優先的時候,必須被滿足的條件要增加一條, 一個桶的各份數據不能都位於相同的一個位置(不在同一個機房)。這裏有一個問題, 假如只有兩個機房, 機房1中有100臺data server, 機房2中只有1臺data server。這個時候, 機房2中data server的壓力必然會非常大。於是這裏產生了一個控制參數 _build_diff_ratio(參見安裝部署文檔)。 當機房差異比率大於這個配置值時, config server也不再build新表。 機房差異比率是如何計出來的呢? 首先找到機器最多的機房,不妨設使RA, data server數量是SA。 那麼其餘的data server的數量記做SB。則機房差異比率=|SA – SB|/SA。 因爲一般我們線上系統配置的COPY_COUNT是3。 在這個情況下, 不妨設只有兩個機房RA和RB, 那麼兩個機房什麼樣的data server數量是均衡的範圍呢? 當差異比率小於 0。5的時候是可以做到各臺data server負載都完全均衡的。這裏有一點要注意:假設RA機房有機器6臺,RB有機器3臺。那麼差異比率 = 6 – 3 / 6 = 0.5。這個時候如果進行擴容,在機房A增加一臺data server,擴容後的差異比率 = 7 – 3 / 7 = 0.57。也就是說,只在機器數多的機房增加data server會擴大差異比率。 如果我們的_build_diff_ratio配置值是0.5。那麼進行這種擴容後, config server會拒絕再繼續build新表。

tair 的一致性和可靠性問題

分佈式系統中的可靠性和一致性是無法同時保證的,因爲我們必須允許網絡錯誤的發生。tair 採用複製技術來提高可靠性,並且爲了提高效率做了一些優化,事實上在沒有錯誤發生的時候,tair 提供的是一種強一致性。但是在有data server發生故障的時候,客戶有可能在一定時間窗口內讀不到最新的數據。 甚至發生最新數據丟失的情況。

參考文獻

Tair:分佈式key/value存儲系統
分佈式K/V存儲方案-Tair



作者:1angxi
鏈接:https://www.jianshu.com/p/ccb17daed766
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

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