Tair緩存系統學習 (數據結構存儲系統)

1、Tair 簡介 
     Tair 是一個類似於map的key/value結構存儲系統(也就是緩存系統),具備標準的特性是:高性能、高擴展、高可靠,也就是傳說中的三高產品,支持分佈式集羣部署。官網說目前支持java和c這兩個版本。 
     適用場景是輕量級緩存應用,爲小文件和零碎文件、固定數據文件存儲的優化。 
2、Tair 存儲方式 
     2.1、非持久化 
             非持久化的tair可以看作是一個分佈式緩存。 
     2.2、持久化 
             持久化的tair是將數據文件放入到磁盤存儲的。持久化的tair有一個非常好的地方就是可以對持久化的文件備份,並且可以備份到不同主機上,通過程序還可以配置成自主備份等非常的靈活。 
             持久化tair中包含了兩個默認的存儲引擎mdb和fdb,當然tair也非常不錯的抽象了持久化層次,也可以採用其他db。 
             mdb是一個高效率的關係型緩存存儲數據庫和memcached對比來看都存在一樣的內存管理方式。當然mdb還支持很多其他特性,比如mdb支持使用share memory ,這使得在重啓 tair數據節點進程時不會導致數據丟失,從而使得應用升級更平滑,也不會導致數據命中率有較大的波動。  mdb主要是使用在需要cache的系統中,爲了減少系統down的影響,採用共享內存的方式,這樣當系統down後,重新啓動後數據還存在。 
             fdb 也上一個簡單高校的關係型緩存存儲數據庫,它的查詢方式比較有趣是採用樹的方式根據數據key的hash值來索引數據,這樣增加了數據查找效率。同時索引數據和業務數據分離,儘量把索引的文件保存在內存中,以便減少io開銷。    fdb是採用類似Tokyo Cabinet實現方式,但這裏爲了性能考慮,會把索引和數據分文件存放,同時把索引文件放在內存中(在部署文檔中可以看到可以配置大小)。 
3、Tair 負債均衡算法 
     分佈式算法是採用的一致性哈希算法。這裏一致性哈希主要解決了分佈式中的平衡性和分散性、一致性。 
     這個地方也有一個比較好的,對於所有的key,分配到q個桶中,桶是負債均衡和數據遷移的基本單位。congfig server(tair的核心接口之一)根據一定的策略把每個桶指派到不同的data server上。因爲數據是按照key做的hash算法。所以可以認爲每個q桶的數據基本是平衡的。那麼保證桶的分佈式均衡性,就保證了數據分佈的均衡性; 
4、Tair 可能存在的缺陷 
     自認爲保證上面了幾點特性時(高性能、高擴展、高可靠等特性),那麼勢必會消耗其他資源,那麼查詢效率有時候可能就會被降低。當然這個也是需要跟分佈式的機器緩存空間、內存等等因素有關係,當緩存系統規模越大,業務系統規模越大時查詢效率可能就會被降低,當然如果這樣又有其他方案來解決這個規模大的問題了,這裏只是說一下,知道有這麼個事就行了。 
     接下來這裏還需要特別提醒下的就是tair在分佈式時一致性和可靠性是無法同時保證的,這個非tair機制問題,實乃是網絡必然會存在問題的,當網絡存在動盪時數據一致性很難在短時間內一致,當然如果網絡沒有問題,tair還是會保持很高的一致性。 
5、Tair 的模塊介紹      
     模塊目前主要爲這三個模塊config server 、data server和storage以及plugin、client、common其中還有一個可選擇的驗證模塊invalid server 。 
      config_server: 模塊主要包括config_server目錄。實現了從配置文件中load進節點的信息,然後根據配置的數據分佈的桶的數量和需要建立的數據的備份數,建立一張數據的分佈表。該表其實是一個數組,元素爲數據存儲的節點的信息,長度爲桶數乘以數據的備份數。config_server還負責對數據節點故障檢測,主要通過心跳來確定數據節點的狀態,但數據節點發生變化(比如增加服務器),就會把前面所描述的數據分佈表發送給數據節點。同時數據節點通過心跳來上報一些統計信息等數據。 
     data_server: 爲數據節點提供服務,主要處理客戶端的請求,還支持了數據的複製,根據前面所描述的數據分佈表,會把負責的主桶的數據發送到對應的備份桶所在節點。 
      storage:  這裏主要實現兩種存儲引擎,其中mdb目錄中實現了內存型的存儲引擎,fdb目錄中實現持久化的存儲引擎。存儲引擎的基本接口定義在storage_manager.hpp。 
     plugin  tair: 支持熱插拔的插件式服務,可以開發自己的插件,然後通知config_server,需要支持這個插件,讓節點進行load。主要的實現場景是性能統計信息。 
      client: 是實現客戶端代碼。 
      common: 目錄提供基礎數據結構和組件,packets目錄提供了通信協議中各種數據包的實現。基礎庫主要包括tbsys和tbnet,其中tbsys是主要的數據結構和文件操作的實現,包括排它鎖和讀寫鎖實現,對線程的包裝,以及配置文件讀寫和分析等。tbnet是主要實現了單線程的網絡讀寫數據流,採用了epoll的模式。      
6、Tair 的擴展功能 
     除了提供get\put\delete以及批量接口外,還存在一些其他使用功能如:version支持,原子計數器,item支持等。  
     version支持:在tair緩存中每一個數據都包含自己的版本號,版本號在每次更新後都會遞增。這個版本號的支持主要目的是由於數據併發導致的更新問題。 
     原子計數器支持:這個支持可以讓tair成爲一個簡單易用的分佈式計算。 
     item支持:這個可以實現一個原子分佈式的fifo的對別。 
7、Tair 核心接口 
     主要的類名: com.taobao.tair.TairManager  
     常用的方法有:delete\get\invalid\put\lock\hide\getVersion等 
8、緩存的使用 
     在考慮構建高性能框架的時候使用緩存,來提供整體的查詢效率和數據的吞吐量,當然計算器科學裏面也有這麼一句話,所有的問題都可以通過增加一個間接層次來解決,那麼在這個思路基礎上提出了幾點想法 
     在數據庫前閒cache並且使用批量添加方法,一次寫入多個緩存數據; 
     可以開啓多線程序同時寫入數據庫,用多個線程同時讀取cache並寫入mysql效率很高; 
     那麼如果對只讀數據做cache的話那麼適合緩存的有,數據很少改變、以讀爲主的數據比如元數據、配置信息和靜態數據; 
     當然緩存使用多了也會帶來隱患爲緩存分配內存多了,用來服務的內存也就少了,應用層可能就會面臨內存不足的壓力,所以在考慮使用緩存時需要非常現實的權衡利弊。 
9、業內緩存框架優缺點對比 
     業內輕量級的緩存框架有ehcache/redis/tair一個重量級別的緩存框架memcached,這裏對這些緩存框架的優缺點做一個梳理給大家做參考。 
     ehcache  :
     優點:易用性特別強、高性能緩存、版本迭代特別快、緩存策略支持多種、可以通過rmi可插入api實現分佈式緩存、具備緩存監聽、支持多緩存實例、提供hibernate的緩存實現、支持非持久化和持久化緩存數據。 
     缺點:使用磁盤空間做cache時非常佔用磁盤空間,kill掉java進程時不能保證數據安全有可能會導致緩存數據丟失或者數據衝突。 
     適用場景:輕量級應用 
     redis :
     優點:非常豐富的數據結構而且都是原子性操作、高速讀寫、支持事務、支持命令行輸入操作性好 
     缺點:沒有自己的內存池在內存分配時存在的碎片會導致性能問題、對內存消耗劇烈(雖然有壓縮方法但還是高)、持久化時定時快照每次都是寫全量數據,代價有些高、aof追加快照只追加增量數據但寫入log特別大。 
     適用場景:輕量級應用 
      memcached :
     優點:協議簡單、基於libevent的事件處理、內置內存存儲方式、不互相通信的分佈式、 
     缺點:數據保存內存中服務進程重啓會導致數據丟失、安全性不足是以root權限運行、內存消耗很大影響性能 
     適用場景:分佈式應用、數據庫前段緩存、服務器間數據共享等 
     不適合場景:不需要分佈式的應用、單機服務、輕量級工程 
10、Tair 如何配置server端  
       10.1 安裝tair服務 
               10.1.1 下載tair源代碼 
                首先安裝tair之前需要確認機器上是否安裝了 automake autoconfig 和 libtool,使用automake --version命令可以查看,一般情況下機器都會安裝的 
               獲得底層庫 tbsys 和 tbnet的源代碼:(svn checkouthttp://code.taobao.org/svn/tb-common-utils/trunk/ tb-common-utils). 
               獲得tair源代碼:(svn checkout http://code.taobao.org/svn/tair/trunk/ tair). 
               安裝boost-devel庫,在用rpm管理軟件包的os上可以使用rpm -q boost-devel查看是否已安裝該庫 
               編譯安裝tbsys和tbnet 
               編譯安裝tair 
               10.1.2 配置環境變量 
                       先指定環境變量 TBLIB_ROOT 爲需要安裝的目錄. 這個環境變量在後續 tair 的編譯安裝中仍舊會被使用到. 比如要安裝到當前用戶的lib目錄下, 則指定 export TBLIB_ROOT="~/lib" 
                10.1.3 安裝tair  
                      進入common文件夾, 執行build.sh進行安裝.  
                      編譯安裝tair:      
                      進入 tair 目錄   
                      運行 bootstrap.sh 運行 configure.  注意, 在運行configue的時候, 可以使用 --with-boost=xxxx 來指定boost的目錄. 使用--with-release=yes 來編譯release版本.   
                      運行 make 進行編譯  
                      運行 make install 進行安裝 
        10.2 配置tair服務 
                tair的運行, 至少需要一個 config server 和一個 data server. 推薦使用兩個 config server 多個data server的方式. 兩個config server有主備之分.  源代碼目錄中 share 目錄下有三個配置文件的樣例, 下面會逐個解說. 
              configserver.conf  group.conf 這兩個配置文件是config server所需要的. 先看這兩個配置文件的配置 
               配置文件 configserver.conf 

[public] 
config_server=x.x.x.x:5198 
config_server=x.x.x.x:5198 
[configserver] 
port=5198 
log_file=logs/config.log 
pid_file=logs/config.pid 
log_level=warn 
group_file=etc/group.conf 
data_dir=data/data 
dev_name=eth0 

              public 下面配置的是兩臺config server的 ip 和端口. 其中排在前面的是主config server. 這一段信息會出現在每一個配置文件中. 請保持這一段信息的嚴格一致. 
              configserver下面的內容是本config server的具體配置: 
              port 端口號, 注意 config server會使用該端口做爲服務端口, 而使用該端口+1 做爲心跳端口           
              log_file 日誌文件 
              pid_file  pid文件, 文件中保存當前進程中的pid 
              log_level 日誌級別 
              group_file 本config server所管理的 group 的配置文件 
              data_dir   本config server自身數據的存放目錄 
              dev_name   所使用的網絡設備名 
              注意: 例子中, 所有的路徑都配置的是相對路徑. 這樣實際上限制了程序啓動時候的工作目錄. 這裏當然可以使用絕對路徑.  
              注意: 程序本身可以把多個config server 或 data server跑在一臺主機上, 只要配置不同的端口號就可以. 但是在配置文件的時候, 他們的數據目錄必須分開, 程序不會對自己的數據目錄加鎖, 所以如果跑在同一主機上的服務, 數據目錄配置相同, 程序自己不會發現, 卻會發生很多莫名其妙的錯誤. 多個服務跑在同一臺主機上, 一般只是在做功能測試的時候使用. 
              配置文件 group.conf 

#group name 
[group_1] 
# data move is 1 means when some data serve down, the migrating will be start. 
# default value is 0 
_data_move=1 
#_min_data_server_count: when data servers left in a group less than this value, config server will stop serve for this group 
#default value is copy count. 
_min_data_server_count=4 
_copy_count=3 
_bucket_number=1023 
_plugIns_list=libStaticPlugIn.so 
_build_strategy=1 #1 normal 2 rack 
_build_diff_ratio=0.6 #how much difference is allowd between different rack 
# diff_ratio =  |data_sever_count_in_rack1 - data_server_count_in_rack2| / max (data_sever_count_in_rack1, data_server_count_in_rack2) 
# diff_ration must less than _build_diff_ratio 
_pos_mask=65535  # 65535 is 0xffff  this will be used to gernerate rack info. 64 bit serverId & _pos_mask is the rack info, 
_server_list=x.x.x.x:5191 
_server_list=x.x.x.x:5191 
_server_list=x.x.x.x:5191 
_server_list=x.x.x.x:5191 
#quota info 
_areaCapacity_list=1,1124000;   
_areaCapacity_list=2,1124000;  

      每個group配置文件可以配置多個group, 這樣一組config server就可以同時服務於多個 group 了. 不同的 group 用group name區分 
     _data_move 當這個配置爲1的時候, 如果發生了某個data server宕機, 則系統會儘可能的通過冗餘的備份對數據進行遷移. 注意, 如果 copy_count 爲大於1的值, 則這個配置無效, 系統總是會發生遷移的. 只有copy_count爲1的時候, 該配置纔有作用.  
     _min_data_server_count  這個是系統中需要存在的最少data server的個數.  當系統中可正常工作的data server的個數小於這個值的時候, 整個系統會停止服務, 等待人工介入 
     _copy_count  這個表示一條數據在系統中實際存儲的份數. 如果tair被用作緩存, 這裏一般配置1. 如果被用來做存儲, 一般配置爲3。 當系統中可工作的data server的數量少於這個值的時候, 系統也會停止工作. 比如 _copy_count 爲3, 而系統中只有 2 臺data server. 這個時候因爲要求一條數據的各個備份必須寫到不同的data server上, 所以系統無法完成寫入操作, 系統也會停止工作的. 
     _bucket_number  這個是hash桶的個數, 一般要 >> data server的數量(10倍以上). 數據的分佈, 負載均衡, 數據的遷移都是以桶爲單位的. 
     _plugIns_list  需要加載的插件的動態庫名 
     _accept_strategy  默認爲0,ds重新連接上cs的時候,需要手動touch group.conf。如果設置成1,則當有ds重新連接會cs的時候,不需要手動touch group.conf。 cs會自動接入該ds。 
     _build_strategy  在分配各個桶到不同的data server上去的時候所採用的策略. 目前提供兩種策略. 配置爲1 則是負載均衡優先, 分配的時候儘量讓各個 data server 的負載均衡. 配置爲 2 的時候, 是位置安全優先, 會盡量將一份數據的不同備份分配到不同機架的機器上. 配置爲3的時候,如果服務器分佈在多個機器上,那麼會優先使用位置安全優先,即策略2. 如果服務器只在一個機架上,那麼退化成策略1,只按負載分佈。 
     _build_diff_ratio 這個值只有當 _build_strategy 爲2的時候纔有意義. 實際上是用來表示不同的機架上機器差異大小的. 當位置安全優先的時候, 如果某個機架上的機器不斷的停止服務, 必然會導致負載的極度不平衡.  當兩個機架上機器數量差異達到一定程度的時候, 系統也不再繼續工作, 等待人工介入. 
     _pos_mask  機架信息掩碼. 程序使用這個值和由ip以及端口生成的64爲的id做與操作, 得到的值就認爲是位置信息.  比如 當此值是65535的時候 是十六進制 0xffff. 因爲ip地址的64位存儲的時候採用的是網絡字節序, 最前32位是端口號, 後32位是網絡字節序的ip地址. 所以0xffff 這個配置, 將認爲10.1.1.1 和 10.2.1.1 是不同的機架. 
     _areaCapacity_list  這是每一個area的配額信息. 這裏的單位是 byte. 需要注意的是, 該信息是某個 area 能夠使用的所有空間的大小. 舉個具體例子:當copy_count爲3 共有5個data server的時候, 每個data server上, 該area實際能使用的空間是這個值/(3 * 5). 因爲fdb使用mdb作爲內部的緩存, 這個值的大小也決定了緩存的效率. 
                   data server的配置文件 

[public] 
config_server=172.23.16.225:5198 
config_server=172.23.16.226:5198 
[tairserver] 
storage_engine=mdb 
mdb_type=mdb_shm 
mdb_shm_path=/mdb_shm_path01 
#tairserver listen port 
port=5191 
heartbeat_port=6191 
process_thread_num=16 
slab_mem_size=22528 
log_file=logs/server.log 
pid_file=logs/server.pid 
log_level=warn 
dev_name=bond0 
ulog_dir=fdb/ulog 
ulog_file_number=3 
ulog_file_size=64 
check_expired_hour_range=2-4 
check_slab_hour_range=5-7 
[fdb] 
# in 
# MB 
index_mmap_size=30 
cache_size=2048 
bucket_size=10223 
free_block_pool_size=8 
data_dir=fdb/data 
fdb_name=tair_fdb 

                   下面解釋一下data server的配置文件: 

public: 部分不再解說
storage_engine: 這個可以配置成fdb或者mdb.分別表示是使用內存存儲數據(mdb)還是使用磁盤(fdb).
mdb_type: 這個是兼容以前版本用的,現在都配成mdb_shm就可以了
mdb_shm_path: 這個是用作映射共享內存的文件.
port: data server的工作端口
heartbeat_port: data server的心跳端口
process_thread_num: 工作線程數.實際上啓動的線程會比這個數值多, 因爲有一些後臺線程.真正處理請求的線程數量是這裏配置的.
slab_mem_size: 所佔用的內存數量.這個值以M爲單位, 如果是mdb, 則是mdb能存放的數據量, 如果是fdb, 此值無意義
ulog_dir: 發生遷移的時候, 日誌文件的文件目錄
ulog_file_number: 用來循環使用的log文件數目
ulog_file_size: 每個日誌文件的大小, 單位是M
check_expired_hour_range: 清理超時數據的時間段.在這個時間段內, 會運行一個後臺進程來清理mdb中的超時數據.一般配置在系統較空閒的時候
check_slab_hour_range: 對slap做平衡的時間段.一般配置在系統較空閒的時候
index_mmap_size: fdb中索引文件映射到內存的大小, 單位是M
cache_size: fdb中用作緩存的共享內存大小, 單位是M
bucket_size: fdb在存儲數據的時候, 也是一個hash算法, 這兒就是hash桶的數目
free_block_pool_size: 這個用來存放fdb中的空閒位置, 便於重用空間
data_dir: fdb的數據文件目錄
fdb_name: fdb數據文件名

        10.3 運行前準備 
                因爲系統使用共享內存作爲數據存儲的空間(mdb)或者緩存空間(fdb), 所以需要先更改配置, 使得程序能夠使用足夠的共享內存.  scripts 目錄下有一個腳本set_shm.sh 是用來做這些修改的, 這個腳本需要root權限來運行. 
        10.4 如何啓動集羣          
               在完成安裝配置之後, 可以啓動集羣了.  啓動的時候需要先啓動data server 然後啓動cofnig server.  如果是爲已有的集羣添加dataserver則可以先啓動dataserver進程然後再修改gruop.conf,如果你先修改group.conf再啓動進程,那麼需要執行touch group.conf;在scripts目錄下有一個腳本 tair.sh 可以用來幫助啓動 tair.sh start_ds 用來啓動data server.   tair.sh start_cs 用來啓動config server.  這個腳本比較簡單, 它要求配置文件放在固定位置, 採用固定名稱.  使用者可以通過執行安裝目錄下的bin下的 tair_server (data server) 和 tair_cfg_svr(config server) 來啓動集羣. 
11 Tair client端(應用中使用) 
        11.1 mavn 配置下載jar包 
               版本號pom文件配置    

              <!--  Tair MC--> 
               <dependency> 
                 <groupId>com.taobao.tair</groupId> 
                 <artifactId>tair-mc-client</artifactId> 
                 <version>1.0.4.18</version> 
               </dependency> 
               <dependency> 
                    <groupId>com.taobao.tair</groupId> 
                    <artifactId>tair-client</artifactId> 
                    <version>2.3.4.49</version> 
               </dependency> 
               <dependency> 
                 <groupId>com.taobao.memberprofile</groupId> 
                 <artifactId>tag-tair</artifactId> 
                 <version>0.8</version> 
               </dependency> 

               工程jar配置 

               <dependency> 
                 <groupId>com.taobao.memberprofile</groupId> 
                 <artifactId>tag-tair</artifactId> 
               </dependency> 
               <!--  Tair MC--> 
               <dependency> 
                      <groupId>com.taobao.tair</groupId> 
                      <artifactId>tair-mc-client</artifactId> 
               </dependency> 
               <dependency> 
                     <groupId>com.taobao.tair</groupId> 
                     <artifactId>tair-client</artifactId> 
               </dependency> 

        11.2 添加Tair代理 

               設計Tair代理初衷、可以有多個不同的對象實例,以應對不同tair對象,不同namespace的情況,如果要增加共享變量就需要注意正確的使用方式,下圖就是所有訪問請求都是通過TairProxy請求到TairManager ,所以針對不同業務的都可以調用對外封裝的Manager。

TairProxy部分實現代碼 
put方法:            

    public boolean put(PrefixKey prefix, String key, Serializable value, int expiredTime) {
        ResultCode result = null;
        if (expiredTime < 1) { 
            // 做不同的處理 
            result = tairManager.put(namespace, prefix.getPrefix() + key, value);
        } else {
            result = tairManager.put(namespace, prefix.getPrefix() + key, value, 0, expiredTime);
        }
        if (result.isSuccess() && result.getCode() == 0) return true;
        log.error("put tair false! namespace:" + namespace + ",prefix:" + prefix + ",key:" + key + "value:" + value + ",exp:" + expiredTime);
        return false;
    }

get方法:

    public Object get(PrefixKey prefix, String key) {
        Result result = tairManager.get(namespace, prefix.getPrefix() + key);
        if (result.isSuccess() && result.getRc().getCode() == 0) {
            DataEntry value = result.getValue();
            if (null != value) {
                return value.getValue();
            }
        }
        return null;
    }

invaild方法:

public boolean invalid(PrefixKey prefix, String key) {
    ResultCode invalid = tairManager.invalid(namespace, prefix.getPrefix() + key);
    if (null != invalid && invalid.getCode() == 0) {
      return true;
    }
    log.error("invalid tair false! namespace:" + namespace + ",prefix:" + prefix + ",key:" + key);
    return false;
  }

           TairManager可以根據需要注入mdb和ldb等等。namespace不同的spring配置文件如下 spring-tair.xml配置文件,同時根據不同的manger需要在這裏聲明。 

${libra2center_tair_mdb_configid}true
${libra2center_tair_market2_configID}true
${libra2center_tair_mcclient_configID}true
${libra2center_tair_market2_configID}true
${libra2center_tair_ldb_configid}true

 log4j.xml配置 : .....
 還有需要配置taircongfigid,這個根據業務需要自己配置地方

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