新聞中心
那些分布式系統(tǒng)設(shè)計(jì)常用的開(kāi)源模塊
2015-11-10 17:45:00
云計(jì)算
分布式 分布式系統(tǒng)是個(gè)由多個(gè)互相連接的處理資源組成的計(jì)算機(jī)系統(tǒng),它們?cè)谡麄€(gè)系統(tǒng)的控制下協(xié)同執(zhí)行同一個(gè)任務(wù),最少依賴(lài)于集中的程序、數(shù)據(jù)或硬件。本文對(duì)大家常用的分布式系統(tǒng)設(shè)計(jì)開(kāi)源模塊進(jìn)行了總結(jié),包括HBase、Nginx、Zookeeper。

創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)營(yíng)銷(xiāo)型網(wǎng)站、網(wǎng)站重做改版、雨城網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)、電子商務(wù)商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為雨城等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
HBase開(kāi)發(fā):
HBase
HBase介紹
HBase - Hadoop Base 是一個(gè)高可靠、高性能的、面向列、可伸縮的分布式系統(tǒng)、利用HBase技術(shù)可在廉價(jià)PC Server上搭建大規(guī)模結(jié)構(gòu)化存儲(chǔ)集群。HBase是Google Bigtable的 java開(kāi)源實(shí)現(xiàn),類(lèi)似Google Bigtable利用GFS作為其文件存儲(chǔ)系統(tǒng),HBase利用Hadoop HDFS作為其文件存儲(chǔ)系統(tǒng),Google運(yùn)行MapReduce來(lái)處理Bigtable中的海量數(shù)據(jù),HBase同樣利用Hadoop MapReduce來(lái)處理HBase中的海量數(shù)據(jù),Google Bigtable利用Chubby作為協(xié)同服務(wù),HBase利用Zookeeper作為協(xié)同服務(wù)。
HBase使用
適用場(chǎng)景
HBase的這些特點(diǎn)適用于數(shù)據(jù)海量、持續(xù)增長(zhǎng)的情況,例如開(kāi)源監(jiān)控平臺(tái)OpenTSDB;網(wǎng)易的logtracer數(shù)據(jù)存儲(chǔ)、監(jiān)控平臺(tái)的數(shù)據(jù)存儲(chǔ);淘寶的交易歷史記錄查詢(xún)系統(tǒng),淘寶指數(shù)等。
Facebook公司整理HBase集群使用的場(chǎng)景如下:
- 需要很高的寫(xiě)吞吐量
- 在大規(guī)模數(shù)據(jù)集中進(jìn)行隨機(jī)訪(fǎng)問(wèn)
- 方便的水平擴(kuò)展
- 結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù)
- 不需要全部的關(guān)系數(shù)據(jù)庫(kù)特性,例如交叉列、交叉表,事務(wù),連接等等
HBase表的設(shè)計(jì)
HBase的表包含如下屬性:
(1)最大版本數(shù):通常是3,如果對(duì)于更新比較頻繁的應(yīng)用完全可以設(shè)置為1,能夠快速的淘汰無(wú)用數(shù)據(jù),對(duì)于節(jié)省存儲(chǔ)空間和提高查詢(xún)速度有效果。
(2)壓縮算法:可以嘗試一下最新出爐的snappy算法,相對(duì)lzo來(lái)說(shuō),壓縮率接近,壓縮效率稍高,解壓效率高很多。
(3)inmemory:表在內(nèi)存中存放,一直會(huì)被忽略的屬性。如果完全將數(shù)據(jù)存放在內(nèi)存中,那么hbase和現(xiàn)在流行的內(nèi)存數(shù)據(jù)庫(kù)memorycached和redis性能差距有多少,尚待實(shí)測(cè)。
(4)bloomfilter:根據(jù)應(yīng)用來(lái)定,看需要精確到rowkey還是column。不過(guò)這里需要理解一下原理,bloomfilter的作用是對(duì)一個(gè)region下查找記錄所在的hfile有用。即如果一個(gè)region下的hfile數(shù)量很多,bloomfilter的作用越明顯。適合那種 compaction趕不上flush速度的應(yīng)用。
默認(rèn)情況下,在創(chuàng)建HBase表的時(shí)候會(huì)自動(dòng)創(chuàng)建一個(gè)region分區(qū),當(dāng)導(dǎo)入數(shù)據(jù)的時(shí)候,所有的HBase客戶(hù)端都向這一個(gè)region寫(xiě)數(shù)據(jù), 直到這個(gè)region足夠大了才進(jìn)行切分。一種可以加快批量寫(xiě)入速度的方法是通過(guò)預(yù)先創(chuàng)建一些空的regions,這樣當(dāng)數(shù)據(jù)寫(xiě)入HBase時(shí),會(huì)按照 region分區(qū)情況,在集群內(nèi)做數(shù)據(jù)的負(fù)載均衡。
有關(guān)預(yù)分區(qū),詳情參見(jiàn):Table Creation: Pre-Creating Regions。
HBase的RowKey設(shè)計(jì)
rowkey是hbase的key-value存儲(chǔ)中的key,通常使用用戶(hù)要查詢(xún)的字段作為rowkey,查詢(xún)結(jié)果作為value??梢酝ㄟ^(guò)設(shè)計(jì)滿(mǎn)足幾種不同的查詢(xún)需求。
數(shù)字rowkey的從大到小排序:原生hbase只支持從小到大的排序,這樣就對(duì)于排行榜一類(lèi)的查詢(xún)需求很尷尬。那么采用rowkey = Integer.MAX_VALUE-rowkey的方式將rowkey進(jìn)行轉(zhuǎn)換,最大的變最小,最小的變最大。在應(yīng)用層再轉(zhuǎn)回來(lái)即可完成排序需求。
rowkey的散列原則:如果rowkey是類(lèi)似時(shí)間戳的方式遞增的生成,建議不要使用正序直接寫(xiě)入rowkey,而是采用reverse的方式反轉(zhuǎn)rowkey,使得rowkey大致均衡分布,這樣設(shè)計(jì)有個(gè)好處是能將regionserver的負(fù)載均衡,否則容易產(chǎn)生所有新數(shù)據(jù)都在一個(gè) regionserver上堆積的現(xiàn)象,這一點(diǎn)還可以結(jié)合table的預(yù)切分一起設(shè)計(jì)。
columnfamily columnfamily盡量少,原因是過(guò)多的columnfamily之間會(huì)互相影響。
Column 對(duì)于column需要擴(kuò)展的應(yīng)用,column可以按普通的方式設(shè)計(jì),但是對(duì)于列相對(duì)固定的應(yīng)用,最好采用將一行記錄封裝到一個(gè)column中的方式,這樣能夠節(jié)省存儲(chǔ)空間。封裝的方式推薦protocolbuffer。
Hbase的row key設(shè)計(jì)較為靈活,根據(jù)業(yè)務(wù)需求可靈活運(yùn)用,在此不展開(kāi)說(shuō)明。Row key 高級(jí)設(shè)計(jì)
HBase Memstore
hbase.hregion.memstore.flush.size參數(shù)注意
hbase.hregion.memstore.flush.size 是出發(fā)系統(tǒng)對(duì)Memstore進(jìn)行flush的閾值,但是該參數(shù)并非單個(gè)Memstore flush的閾值而是一個(gè)Region內(nèi)所有Memstore的大小之后閾值
深入理解HBase Memstore
MemStore是HBase非常重要的組成部分,深入理解MemStore的運(yùn)行機(jī)制、工作原理、相關(guān)配置,對(duì)HBase集群管理以及性能調(diào)優(yōu)有非常重要的幫助。
首先通過(guò)簡(jiǎn)單介紹HBase的讀寫(xiě)過(guò)程來(lái)理解一下MemStore到底是什么,在何處發(fā)揮作用,如何使用到以及為什么要用MemStore。
當(dāng)RegionServer(RS)收到寫(xiě)請(qǐng)求的時(shí)候(write request),RS會(huì)將請(qǐng)求轉(zhuǎn)至相應(yīng)的Region。每一個(gè)Region都存儲(chǔ)著一些列(a set of rows)。根據(jù)其列族的不同,將這些列數(shù)據(jù)存儲(chǔ)在相應(yīng)的列族中(Column Family,簡(jiǎn)寫(xiě)CF)。不同的CFs中的數(shù)據(jù)存儲(chǔ)在各自的HStore中,HStore由一個(gè)Memstore及一系列HFile組成。 Memstore位于RS的主內(nèi)存中,而HFiles被寫(xiě)入到HDFS中。當(dāng)RS處理寫(xiě)請(qǐng)求的時(shí)候,數(shù)據(jù)首先寫(xiě)入到Memstore,然后當(dāng)?shù)竭_(dá)一定的閥值的時(shí)候,Memstore中的數(shù)據(jù)會(huì)被刷到HFile中。
用到Memstore最主要的原因是:存儲(chǔ)在HDFS上的數(shù)據(jù)需要按照row key 排序。而HDFS本身被設(shè)計(jì)為順序讀寫(xiě)(sequential reads/writes),不允許修改。這樣的話(huà),HBase就不能夠高效的寫(xiě)數(shù)據(jù),因?yàn)橐獙?xiě)入到HBase的數(shù)據(jù)不會(huì)被排序,這也就意味著沒(méi)有為將來(lái)的檢索優(yōu)化。為了解決這個(gè)問(wèn)題,HBase將最近接收到的數(shù)據(jù)緩存在內(nèi)存中(in Memstore),在持久化到HDFS之前完成排序,然后再快速的順序?qū)懭際DFS。需要注意的一點(diǎn)是實(shí)際的HFile中,不僅僅只是簡(jiǎn)單地排序的列數(shù)據(jù)的列表,詳見(jiàn)Apache HBase I/O – HFile。
除了解決“無(wú)序”問(wèn)題外,Memstore還有一些其他的好處,例如:
作為一個(gè)內(nèi)存級(jí)緩存,緩存最近增加數(shù)據(jù)。一種顯而易見(jiàn)的場(chǎng)合是,新插入數(shù)據(jù)總是比老數(shù)據(jù)頻繁使用。
在持久化寫(xiě)入之前,在內(nèi)存中對(duì)Rows/Cells可以做某些優(yōu)化。比如,當(dāng)數(shù)據(jù)的version被設(shè)為1的時(shí)候,對(duì)于某些CF的一些數(shù)據(jù),Memstore緩存了數(shù)個(gè)對(duì)該Cell的更新,在寫(xiě)入HFile的時(shí)候,僅需要保存一個(gè)最新的版本就好了,其他的都可以直接拋棄。
有一點(diǎn)需要特別注意:每一次Memstore的flush,會(huì)為每一個(gè)CF創(chuàng)建一個(gè)新的HFile。在讀方面相對(duì)來(lái)說(shuō)就會(huì)簡(jiǎn)單一些:HBase首先檢查請(qǐng)求的數(shù)據(jù)是否在Memstore,不在的話(huà)就到HFile中查找,最終返回merged的一個(gè)結(jié)果給用戶(hù)。
HBase Memstore關(guān)注要點(diǎn)
迫于以下幾個(gè)原因,HBase用戶(hù)或者管理員需要關(guān)注Memstore并且要熟悉它是如何被使用的:
- Memstore有許多配置可以調(diào)整以取得好的性能和避免一些問(wèn)題。HBase不會(huì)根據(jù)用戶(hù)自己的使用模式來(lái)調(diào)整這些配置,你需要自己來(lái)調(diào)整。
- 頻繁的Memstore flush會(huì)嚴(yán)重影響HBase集群讀性能,并有可能帶來(lái)一些額外的負(fù)載。
- Memstore flush的方式有可能影響你的HBase schema設(shè)計(jì)
Memstore配置要點(diǎn)
第一組是關(guān)于觸發(fā)“普通”flush,這類(lèi)flush發(fā)生時(shí),并不影響并行的寫(xiě)請(qǐng)求。該類(lèi)型flush的配置項(xiàng)有:
hbase.hregion.memstore.flush.size
base.regionserver.global.memstore.lowerLimit
需要注意的是第一個(gè)設(shè)置是每個(gè)Memstore的大小,當(dāng)你設(shè)置該配置項(xiàng)時(shí),你需要考慮一下每臺(tái)RS承載的region總量??赡芤婚_(kāi)始你設(shè)置的該值比較小,后來(lái)隨著region增多,那么就有可能因?yàn)榈诙€(gè)設(shè)置原因Memstore的flush觸發(fā)會(huì)變?cè)缭S多。
第二組設(shè)置主要是出于安全考慮:有時(shí)候集群的“寫(xiě)負(fù)載”非常高,寫(xiě)入量一直超過(guò)flush的量,這時(shí),我們就希望memstore不要超過(guò)一定的安全設(shè)置。在這種情況下,寫(xiě)操作就要被阻止(blocked)一直到memstore恢復(fù)到一個(gè)“可管理”(manageable)的大小。該類(lèi)型 flush配置項(xiàng)有:
hbase.regionserver.global.memstore.upperLimit
hbase.hregion.memstore.block.multiplier
某個(gè)節(jié)點(diǎn)“寫(xiě)阻塞”對(duì)該節(jié)點(diǎn)來(lái)說(shuō)影響很大,但是對(duì)于整個(gè)集群的影響更大。HBase設(shè)計(jì)為:每個(gè)Region僅屬于一個(gè)RS但是“寫(xiě)負(fù)載”是均勻分布于整個(gè)集群(所有Region上)。有一個(gè)如此“慢”的節(jié)點(diǎn),將會(huì)使得整個(gè)集群都會(huì)變慢(最明顯的是反映在速度上)。
提示:嚴(yán)重關(guān)切Memstore的大小和Memstore Flush Queue的大小。理想情況下,Memstore的大小不應(yīng)該達(dá)到 hbase.regionserver.global.memstore.upperLimit的設(shè)置,Memstore Flush Queue 的size不能持續(xù)增長(zhǎng)。
頻繁的Memstore Flushes帶來(lái)的影響
要避免“寫(xiě)阻塞”,貌似讓Flush操作盡量的早于達(dá)到觸發(fā)“寫(xiě)操作”的閾值為宜。但是,這將導(dǎo)致頻繁的Flush操作,而由此帶來(lái)的后果便是讀性能下降以及額外的負(fù)載。
每次的Memstore Flush都會(huì)為每個(gè)CF創(chuàng)建一個(gè)HFile。頻繁的Flush就會(huì)創(chuàng)建大量的HFile。這樣HBase在檢索的時(shí)候,就不得不讀取大量的HFile,讀性能會(huì)受很大影響。
為預(yù)防打開(kāi)過(guò)多HFile及避免讀性能惡化,HBase有專(zhuān)門(mén)的HFile合并處理(HFile Compaction Process)。HBase會(huì)周期性的合并數(shù)個(gè)小HFile為一個(gè)大的HFile。明顯的,有Memstore Flush產(chǎn)生的HFile越多,集群系統(tǒng)就要做更多的合并操作(額外負(fù)載)。更糟糕的是:Compaction處理是跟集群上的其他請(qǐng)求并行進(jìn)行的。當(dāng) HBase不能夠跟上Compaction的時(shí)候(同樣有閾值設(shè)置項(xiàng)),會(huì)在RS上出現(xiàn)“寫(xiě)阻塞”。像上面說(shuō)到的,這是最最不希望的。
提示:嚴(yán)重關(guān)切RS上Compaction Queue 的size。要在其引起問(wèn)題前,阻止其持續(xù)增大。
想了解更多HFile 創(chuàng)建和合并,可參看 Visualizing HBase Flushes And Compactions。
理想情況下,在不超過(guò)hbase.regionserver.global.memstore.upperLimit的情況下,Memstore應(yīng)該盡可能多的使用內(nèi)存(配置給Memstore部分的,而不是真?zhèn)€Heap的)。
HLog (WAL) Size & Memstore Flush
當(dāng)數(shù)據(jù)被寫(xiě)入時(shí)會(huì)默認(rèn)先寫(xiě)入Write-ahead Log(WAL)。WAL中包含了所有已經(jīng)寫(xiě)入Memstore但還未Flush到HFile的更改(edits)。在Memstore中數(shù)據(jù)還沒(méi)有持久化,當(dāng)RegionSever宕掉的時(shí)候,可以使用WAL恢復(fù)數(shù)據(jù)。
當(dāng)WAL(在HBase中成為HLog)變得很大的時(shí)候,在恢復(fù)的時(shí)候就需要很長(zhǎng)的時(shí)間。因此,對(duì)WAL的大小也有一些限制,當(dāng)達(dá)到這些限制的時(shí)候,就會(huì)觸發(fā)Memstore的flush。Memstore flush會(huì)使WAL 減少,因?yàn)閿?shù)據(jù)持久化之后(寫(xiě)入到HFile),就沒(méi)有必要在WAL中再保存這些修改。有兩個(gè)屬性可以配置:
l hbase.regionserver.hlog.blocksize
l hbase.regionserver.maxlogs
WAL的最大值由hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize (2GB by default)決定。一旦達(dá)到這個(gè)值,Memstore flush就會(huì)被觸發(fā)。所以,當(dāng)你增加Memstore的大小以及調(diào)整其他的Memstore的設(shè)置項(xiàng)時(shí),你也需要去調(diào)整HLog的配置項(xiàng)。否則,WAL 的大小限制可能會(huì)首先被觸發(fā),因而,你將利用不到其他專(zhuān)門(mén)為Memstore而設(shè)計(jì)的優(yōu)化。拋開(kāi)這些不說(shuō),通過(guò)WAL限制來(lái)觸發(fā)Memstore的 flush并非最佳方式,這樣做可能會(huì)會(huì)一次flush很多Region,盡管“寫(xiě)數(shù)據(jù)”是很好的分布于整個(gè)集群,進(jìn)而很有可能會(huì)引發(fā)flush“大風(fēng)暴”
提示:最好將hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs 設(shè)置為稍微大于hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE.
HBase Compaction
Compaction是buffer->flush->merge的Log-Structured Merge-Tree模型的關(guān)鍵操作,主要起到如下幾個(gè)作用:
- 合并文件
- 清除刪除、過(guò)期、多余版本的數(shù)據(jù)
- 提高讀寫(xiě)數(shù)據(jù)的效率
HBase 有兩種方式的Compaction,Minor和Major
- Minor Compaction操作只用來(lái)做部分文件的合并操作以及包括minVersion=0并且設(shè)置ttl的過(guò)期版本清理,不做任何刪除數(shù)據(jù)、多版本數(shù)據(jù)的清理工作。
- Major Compaction操作是對(duì)Region下的HStore下的所有StoreFile執(zhí)行合并操作,最終的結(jié)果是整理合并出一個(gè)文件。
#p#
Compaction如何發(fā)生
在什么情況下會(huì)發(fā)生Compaction呢?
CompactionChecker是RS上的工作線(xiàn)程,設(shè)置執(zhí)行周期是通過(guò)threadWakeFrequency指定,大小通過(guò) hbase.server.thread.wakefrequency配置(默認(rèn)10000),然后乘以默認(rèn)倍數(shù)multiple(1000),毫秒時(shí)間轉(zhuǎn)換為秒。因此,在不做參數(shù)修改的情況下,CompactionChecker大概是2hrs, 46mins, 40sec執(zhí)行一次。
首先,對(duì)于HRegion里的每個(gè)HStore進(jìn)行一次判斷,needsCompaction()判斷是否足夠多的文件觸發(fā)了Compaction 的條件。條件為:HStore中StoreFIles的個(gè)數(shù) – 正在執(zhí)行Compacting的文件個(gè)數(shù) > minFilesToCompact
操作:以最低優(yōu)先級(jí)提交Compaction申請(qǐng)。
在大多數(shù)情況下,Major是發(fā)生在storefiles和filesToCompact文件個(gè)數(shù)相同,并且滿(mǎn)足各種條件的前提下執(zhí)行。這里進(jìn)行幾個(gè)參數(shù)配置的簡(jiǎn)介:
- hbase.hregion.majorcompaction: 設(shè)置系統(tǒng)進(jìn)行一次MajorCompaction的啟動(dòng)周期,如果設(shè)置為0,則系統(tǒng)不會(huì)主動(dòng)觸發(fā)MC過(guò)程。
- hbase.hstore.compaction.max:設(shè)置執(zhí)行Compaction(包括Major &Minor)的待合并文件的最大個(gè)數(shù)。默認(rèn)值為10,如果超過(guò)該設(shè)置值,會(huì)對(duì)部分文件執(zhí)行一次MinorCompaction,選擇算法如 Figure1。
- hbase.hstore.compactionThreshold: 設(shè)置執(zhí)行Compaction(Major && Minor)操作的閾值,默認(rèn)是3,如果想降低過(guò)頻繁的合并操作,可以稍微調(diào)大一點(diǎn),對(duì)于HBase負(fù)載較重的系統(tǒng),可以設(shè)置成5。
Compaction對(duì)讀寫(xiě)操作的影響
Compaction與Flush不同之處在于:Flush是針對(duì)一個(gè)Region整體執(zhí)行操作,而Compaction操作是針對(duì)Region上的一個(gè)Store而言,因此,從邏輯上看,F(xiàn)lush操作粒度較大。這屬于一個(gè)LSM存儲(chǔ)模型最核心的設(shè)計(jì):
Flush操作如果只選擇某個(gè)Region的Store內(nèi)的MemStore寫(xiě)入磁盤(pán),而不是統(tǒng)一寫(xiě)入磁盤(pán),那么HLog上key的一致性在Reigon不同ColumnFamily(Store)下的MemStore內(nèi)就會(huì)有不一致的key區(qū)間。
如下圖所示,我們假定該RegionServer上僅有一個(gè)Region,由于不同的Row是在列簇上有所區(qū)別,就會(huì)出現(xiàn)有些不同Store內(nèi)占用的內(nèi)存不一致的情況,這里會(huì)根據(jù)整體內(nèi)存使用的情況,或者RS使用內(nèi)存的情況來(lái)決定是否執(zhí)行Flush操作。如果僅僅刷入使用內(nèi)存較大的 memstore,那么在使用的過(guò)程中,一是Scan操作在執(zhí)行時(shí)就不夠統(tǒng)一,二是在HLog Replayer還原Region內(nèi)Memstore故障前的狀態(tài),只需根據(jù)Hlog的Flush_marker的標(biāo)記位來(lái)執(zhí)行Replay即可。
Compaction執(zhí)行結(jié)束之后會(huì)生成臨時(shí)文件,臨時(shí)文件所在的hdfs位置如下:/hbase-weibo/bi_weibo_cluster /ffd87a50c3df3080183d4910d183d0ee/.tmp ffd87a50c3df3080183d4910d183d0ee 是bi_weibo_cluster表格的Region名。臨時(shí)文件的意義在于,在Compaction執(zhí)行期間,對(duì)于原數(shù)據(jù)訪(fǎng)問(wèn)沒(méi)有影響。 Compaction執(zhí)行合并操作生成的文件生效過(guò)程,需要對(duì)Store的寫(xiě)操作加鎖,阻塞Store內(nèi)的更新操作,直到更新Store的 storeFiles完成為止。(注意,這個(gè)操作過(guò)程執(zhí)行會(huì)影響到更新服務(wù),但是影響不會(huì)太大)
對(duì)于讀服務(wù)的影響,類(lèi)似于Flush操作,也是通過(guò)ChangedReaderObserver為StoreScanner注冊(cè)監(jiān)聽(tīng)類(lèi)來(lái)實(shí)現(xiàn)的。具體內(nèi)容可以參考之前的”HBase Flush操作流程以及對(duì)讀寫(xiě)服務(wù)的影響”。
HBase Region Server Compact過(guò)程占用大量網(wǎng)絡(luò)出口帶寬的問(wèn)題
該問(wèn)題較為普遍,當(dāng)Regionserver帶寬被大量占用的時(shí)候,客戶(hù)端的寫(xiě)入基本全都超時(shí),有網(wǎng)友分析并提供了解決方案。
HBase Region
Region的分配問(wèn)題
當(dāng)Region數(shù)量變多的時(shí)候,就需要把它們分配給不同的Region Server來(lái)保證每個(gè)Region Server都有事情做,但是當(dāng)region數(shù)量遠(yuǎn)遠(yuǎn)大于Region Server個(gè)數(shù)的時(shí)候,就需要保證一個(gè)load balance問(wèn)題,不能讓一個(gè)Region Server上有大量的regions,而其他Region Server上只有幾個(gè)regions,這樣很可能導(dǎo)致負(fù)載不均衡。
Region split問(wèn)題
hbase通過(guò)split region實(shí)現(xiàn)水平的sharding,但在split的過(guò)程中舊的region會(huì)下線(xiàn),新region還會(huì)做compaction,中間有一段時(shí)間大量的數(shù)據(jù)不能被讀寫(xiě),這對(duì)于我們這種online系統(tǒng)是不能忍受的。我們同樣禁掉自動(dòng)的split,而在晚上系統(tǒng)空閑時(shí)執(zhí)行我們的splittool手動(dòng)的split。
禁用方法把hbase.hregion.max.filesize參數(shù)值設(shè)成較大的值例如536870912000
(500g)
在對(duì)Region進(jìn)行手工split的過(guò)程中,出現(xiàn)以下異常
./hbase org.apache.hadoop.hbase.util.RegionSplitter -r lsmp_lottery_presplit HexStringSplit
這個(gè)HBase的一個(gè)bug,HBase0.94 出現(xiàn)以上錯(cuò)誤,需要打補(bǔ)丁即可,https://issues.apache.org/jira/browse/HBASE-7048
HBase寫(xiě)客戶(hù)端優(yōu)化
多HTable并發(fā)寫(xiě)
創(chuàng)建多個(gè)HTable客戶(hù)端用于寫(xiě)操作,提高寫(xiě)數(shù)據(jù)的吞吐量。另外還可以使用HTablePool來(lái)實(shí)現(xiàn)多線(xiàn)程寫(xiě)入。
HTable參數(shù)設(shè)置
- Auto Flush
通過(guò)調(diào)用HTable.setAutoFlush(false)方法可以將HTable寫(xiě)客戶(hù)端的自動(dòng)flush關(guān)閉,這樣可以批量寫(xiě)入數(shù)據(jù)到 HBase,而不是有一條put就執(zhí)行一次更新,只有當(dāng)put填滿(mǎn)客戶(hù)端寫(xiě)緩存時(shí),才實(shí)際向HBase服務(wù)端發(fā)起寫(xiě)請(qǐng)求。默認(rèn)情況下auto flush是開(kāi)啟的。
- Write Buffer
通過(guò)調(diào)用HTable.setWriteBufferSize(writeBufferSize)方法可以設(shè)置 HTable客戶(hù)端的寫(xiě)buffer大小,如果新設(shè)置的buffer小于當(dāng)前寫(xiě)buffer中的數(shù)據(jù)時(shí),buffer將會(huì)被flush到服務(wù)端。其 中,writeBufferSize的單位是byte字節(jié)數(shù),可以根據(jù)實(shí)際寫(xiě)入數(shù)據(jù)量的多少來(lái)設(shè)置該值。
- WAL Flag
在HBae中,客戶(hù)端向集群中的RegionServer提交數(shù)據(jù)時(shí)(Put/Delete操作),首先會(huì)先寫(xiě)WAL(Write Ahead Log)日志(即HLog,一個(gè)RegionServer上的所有Region共享一個(gè)HLog),只有當(dāng)WAL日志寫(xiě)成功后,再接著寫(xiě) MemStore,然后客戶(hù)端被通知提交數(shù)據(jù)成功;如果寫(xiě)WAL日志失敗,客戶(hù)端則被通知提交失敗。這樣做的好處是可以做到RegionServer宕機(jī) 后的數(shù)據(jù)恢復(fù)。
因此,對(duì)于相對(duì)不太重要的數(shù)據(jù),可以在Put/Delete操作時(shí),通過(guò)調(diào)用Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函數(shù),放棄寫(xiě)WAL日志,從而提高數(shù)據(jù)寫(xiě)入的性能。
需要注意的是:謹(jǐn)慎選擇關(guān)閉WAL日志,因?yàn)檫@樣的話(huà),一旦RegionServer宕機(jī),Put/Delete的數(shù)據(jù)將會(huì)無(wú)法根據(jù)WAL日志進(jìn)行恢復(fù)。
批量寫(xiě)入
通過(guò)調(diào)用HTable.put(Put)方法可以將一個(gè)指定的row key記錄寫(xiě)入HBase,同樣HBase提供了另一個(gè)方法:通過(guò)調(diào)用HTable.put(List)方法可以將指定的row key列表,批量寫(xiě)入多行記錄,這樣做的好處是批量執(zhí)行,只需要一次網(wǎng)絡(luò)I/O開(kāi)銷(xiāo),這對(duì)于對(duì)數(shù)據(jù)實(shí)時(shí)性要求高,網(wǎng)絡(luò)傳輸RTT高的情景下可能帶來(lái)明顯的 性能提升。
多線(xiàn)程并發(fā)寫(xiě)
在客戶(hù)端開(kāi)啟多個(gè)HTable寫(xiě)線(xiàn)程,每個(gè)寫(xiě)線(xiàn)程負(fù)責(zé)一個(gè)HTable對(duì)象的flush操作,這樣結(jié)合定時(shí)flush和寫(xiě) buffer(writeBufferSize),可以既保證在數(shù)據(jù)量小的時(shí)候,數(shù)據(jù)可以在較短時(shí)間內(nèi)被flush(如1秒內(nèi)),同時(shí)又保證在數(shù)據(jù)量大的 時(shí)候,寫(xiě)buffer一滿(mǎn)就及時(shí)進(jìn)行flush。
其他
enable和disable表時(shí)出現(xiàn)表未disable/enable異常處理
今天在為表增加LZO壓縮,在enable表時(shí),發(fā)現(xiàn)耗時(shí)很長(zhǎng)都未結(jié)束,就ctrl+c退出hbase shell,再進(jìn)入繼續(xù)enable表,但此時(shí)出現(xiàn)如下錯(cuò)誤:
錯(cuò)誤說(shuō)表未禁用,但進(jìn)行disable表操作時(shí),又出現(xiàn)如下錯(cuò)誤:
那肯定是剛才強(qiáng)行退出導(dǎo)致出問(wèn)題了,根據(jù)大家的經(jīng)驗(yàn),指出這是因?yàn)閦ookeeper保持了要enable的這個(gè)表信息,只需要登錄zk刪除該記錄就行。
登錄到zookeeper也有兩種方式,一是到zk目錄運(yùn)行腳本連接,而是直接在hbase安裝目錄bin下運(yùn)行:
hbase zkcli
都是小寫(xiě)字母。之后就能連接上zookeeper了,跟著刪除/hbase/table下對(duì)應(yīng)的表項(xiàng)就行:
delete /hbase/table/user_video_recommend2
之后就可以成功的enable表了。
如果此時(shí)仍然失敗,則可以運(yùn)行一下命了修復(fù)META:
hbase hbck -fixMeta -fixAssignments
HBase元數(shù)據(jù)損壞修復(fù)
hbase hbck -repair -sidelineDir hdfs://mycluster/hbase/rbu
但是出問(wèn)題的時(shí)候有可能出現(xiàn)RIT中大量任務(wù)無(wú)法結(jié)束,只要沒(méi)有長(zhǎng)期PENDING_OPEN的任務(wù),就可以先將有問(wèn)題的表先disable一下。這里要提到的是hbase的hbck很弱,會(huì)形成一個(gè)死循環(huán),一方面region由于元數(shù)據(jù)破壞無(wú)法開(kāi)啟需要repair,造成大量的RIT長(zhǎng)期hang 在上面,但是repair的操作卻要等待這些RIT結(jié)束才能繼續(xù),而且repair操作也不是離線(xiàn)操作,必須要先保證hbase能正常起來(lái)。因此打破死循環(huán)的關(guān)鍵就是先處理掉RIT中hang的操作,這需要經(jīng)驗(yàn)和仔細(xì)排查。
如果出現(xiàn)長(zhǎng)期的pending_open,則要觀察pending_open的原因,要嘗試解決,這次我們出現(xiàn)的問(wèn)題是元數(shù)據(jù)出錯(cuò),某個(gè) Region的對(duì)row的加鎖范圍超出region本身的key的取值范圍,引起不斷地PENING_OPEN,通過(guò)離線(xiàn)的merge操作將該 region隨便找了個(gè)region merge下解決了該問(wèn)題,./hbase org.apache.hadoop.hbase.util.Merge
最后可通過(guò)hbck恢復(fù)元數(shù)據(jù),但是hbck恢復(fù)過(guò)程中可能會(huì)丟失數(shù)據(jù),因此要慎用,最好通過(guò)SNAPSHOT做備份來(lái)解決這類(lèi)問(wèn)題
HBaseClient異常:java.io.IOException: Connection reset by peer
hbase客戶(hù)端每次和regionserver交互的時(shí)候,都會(huì)在服務(wù)器端生成一個(gè)租約(Lease),租約的有效期由參數(shù)hbase.regionserver.lease.period確定。
客戶(hù)端去regionserver取 數(shù)據(jù)的時(shí)候,hbase中存得數(shù)據(jù)量很大并且很多region的時(shí)候的,客戶(hù)端請(qǐng)求的region不在內(nèi)存中,或是沒(méi)有被cache住,需要從磁盤(pán)中加 載,如果這時(shí)候加載需要的時(shí)間超過(guò)hbase.regionserver.lease.period所配置的時(shí)間,并且客戶(hù)端沒(méi)有和 regionserver報(bào)告其還活著,那么regionserver就會(huì)認(rèn)為本次租約已經(jīng)過(guò)期,并從LeaseQueue從刪除掉本次租約,當(dāng) regionserver加載完成后,拿已經(jīng)被刪除的租約再去取數(shù)據(jù)的時(shí)候,就會(huì)出現(xiàn)如上的錯(cuò)誤現(xiàn)象。
解決的辦法:
1)、適當(dāng)?shù)脑龃?hbase.regionserver.lease.period參數(shù)的值,默認(rèn)是1分鐘
2)、增大regionserver的cache大小
#p#
Nginx:
概要介紹
Nginx是一款高性能的HTTP和反向代理服務(wù)器,也是一個(gè)IMAP/POP3/SMTP代理服務(wù)器。第一個(gè)公開(kāi)版本發(fā)布于2004年10月4日,其將源代碼以類(lèi)BSD許可證的形式發(fā)布,因它的穩(wěn)定性、豐富的功能集和低系統(tǒng)資源的消耗而聞名。Nginx的最新穩(wěn)定版本是1.4.4。與Apache、Lighttpd不同,Nginx充分使用異步邏輯,削減了上下文調(diào)度開(kāi)銷(xiāo),所以并發(fā)服務(wù)能力更強(qiáng)。Nginx整體采用模塊化設(shè)計(jì),有豐富的模塊庫(kù)和第三方模塊庫(kù),配置靈活。 在Linux操作系統(tǒng)下,Nginx使用epoll事件模型,得益于此,其在效率相當(dāng)高。在國(guó)內(nèi),各大主流站點(diǎn)都在使用Nginx作為Web服務(wù)器或反向代理服務(wù)器。據(jù)統(tǒng)計(jì),截止今年2013年7月,在全球Top 1000網(wǎng)站中,有34.9%的網(wǎng)站在使用Nginx,這使得Nginx超越Apache,成為了TOP站點(diǎn)最信任的Web服務(wù)器。下圖可見(jiàn)Nginx在 TOP站點(diǎn)的受歡迎程度(見(jiàn)橙色條目)。
主要功能
- 輕松搞定C10K問(wèn)題,且占內(nèi)存極少,據(jù)稱(chēng)C10K idle連接僅需內(nèi)存2.5MB;
- 處理靜態(tài)文件的性能非常優(yōu)秀,支持sendfile、AIO等高級(jí)特性,支持靜態(tài)文件Auto Index;
- 支持反向代理,對(duì)后端服務(wù)進(jìn)行健康檢查;
- 支持反向代理緩存,避免與后端的頻繁交互;
- 支持郵件服務(wù)代理:IMAP、POP3、SMTP;
- 支持負(fù)載均衡策略,包括:round-robin、weight、hash、consistent hash、fair等;
- 支持HTTPS安全訪(fǎng)問(wèn);
- 支持虛擬主機(jī)的配置;
- 支持基本W(wǎng)eb認(rèn)證機(jī)制;
- 支持基于IP的訪(fǎng)問(wèn)控制;
- 支持URL規(guī)則重寫(xiě);
- 支持并發(fā)連接數(shù)限制和單條連接的限速;
- 支持WebSocket和SPDY;
- 支持Referer 過(guò)濾防盜鏈;
- 支持靈活配置輸出日志;
擴(kuò)展功能
- 能夠在配置文件中嵌入ngx_perl和ngx_lua腳本,擴(kuò)展功能超強(qiáng);
- 提供了與Memcached、Redis、MySQL、PostgreSQL、MangoDB、MogileFS、TaobaoFS等常見(jiàn)服務(wù)器交互的模塊;
- Image 模塊實(shí)現(xiàn)了簡(jiǎn)單的圖片功能,包括:縮略、裁剪、質(zhì)量參數(shù)等;
- 視頻支持包括:FLV和MP4視頻播放,RTMP模塊具有在線(xiàn)ffmpeg轉(zhuǎn)碼以及M3U8的支持;
- PageSpeed模塊實(shí)現(xiàn)網(wǎng)頁(yè)加速功能,具體包括:圖片優(yōu)化,CSS&JS 壓縮合并,資源內(nèi)聯(lián),HTML重寫(xiě);
- 與后端Tomcat的連接可以使用AJP 模塊進(jìn)行協(xié)議優(yōu)化;
- Push 模塊實(shí)現(xiàn)長(zhǎng)連接輪詢(xún)服務(wù),實(shí)現(xiàn)Web推送服務(wù)(Comet);
- UploadRate 模塊實(shí)現(xiàn)上傳的流量限制功能;
常用配置
虛擬主機(jī)
- http {
- index index.html;
- # 虛擬主機(jī) www.domain1.com;
- server {
- server_name www.domain1.com;
- access_log logs/domain1.access.log main;
- root /var/www/domain1.com/htdocs;
- }
- # 虛擬主機(jī) www.domain2.com
- server {
- server_name www.domain2.com;
- access_log logs/domain2.access.log main;
- root /var/www/domain2.com/htdocs;
- }
- }
負(fù)載均衡
- # 默認(rèn)的負(fù)載均衡,Round-Robin
- upstream backend1 {
- server backend1.cdxwcx.com;
- server backend2.cdxwcx.com;
- server backend3.cdxwcx.com;
- }
- # 基于權(quán)重的負(fù)載均衡
- upstream backend2 {
- server backend1.cdxwcx.com weight=5;
- server backend2.cdxwcx.com weight=2;
- server backend3.cdxwcx.com weight=3;
- }
- # 基于request_uri hash的負(fù)載均衡
- upstream backend3 {
- server backend1.cdxwcx.com;
- server backend2.cdxwcx.com;
- server backend3.cdxwcx.com;
- hash $request_uri;
- }
- # 基于request_uri consistent hash的負(fù)載均衡
- upstream backend4 {
- server backend1.cdxwcx.com;
- server backend2.cdxwcx.com;
- server backend3.cdxwcx.com;
- consistent_hash $request_uri;
- }
- # 基于后端響應(yīng)時(shí)間的負(fù)載均衡
- upstream backend5 {
- server backend1.cdxwcx.com;
- server backend2.cdxwcx.com;
- server backend3.cdxwcx.com;
- fair;
- }
- server {
- location / {
- proxy_pass http://backend1;
- # proxy_pass http://backend2;
- # proxy_pass http://backend3;
- # proxy_pass http://backend4;
- # proxy_pass http://backend5;
- }
- }
以上可見(jiàn),Nginx支持的負(fù)載均衡策略非常全面,總結(jié)有五種策略,即:
- Round-Robin:輪詢(xún);
- Weight:基于權(quán)重;
- Hash:基于Nginx內(nèi)置參數(shù)的哈希,內(nèi)置參數(shù)可以為ClientIP、Request_URI等;
- Consistent Hash:基于Nginx內(nèi)置參數(shù)的一致性哈希;
- Fair:公平策略,根據(jù)響應(yīng)時(shí)間來(lái)判定應(yīng)該將請(qǐng)求發(fā)往那個(gè)后端服務(wù)器;
除此之外,Nginx負(fù)載均衡還支持以下關(guān)鍵參數(shù):
- down:表示當(dāng)前的server暫時(shí)不參與負(fù)載;
- max_fails:允許重試的最大次數(shù),當(dāng)達(dá)到該次數(shù),Nginx將暫停向該server發(fā)送請(qǐng)求;
- fail_timeout:max_fails次失敗后,暫停的時(shí)間;
- backup: 其它所有的非backup機(jī)器down或者忙的時(shí)候,請(qǐng)求backup機(jī)器,這臺(tái)機(jī)器壓力會(huì)最輕;
流量限制
- server {
- location / {
- root html; # 靜態(tài)文件root目錄
- limit_rate_after 1m; # 文件下載1M后
- limit_rate 100k; # 限制其下載流量為100k
- }
- }
注:limit_rate只能限制單條連接的流量
連接限制
- http {
- # 并發(fā)連接統(tǒng)計(jì)粒度為 $binary_remote_addr
- # 粒度還可以為 $request_uri 等任意的Nginx內(nèi)置變量
- limit_conn_zone $binary_remote_addr zone=one:2m;
- server {
- location /download {
- limit_conn one 100; # 同一個(gè)remote_addr只允許100個(gè)并發(fā)連接
- }
- }
- }
代理緩存
- server {
- # 設(shè)置Web緩存區(qū)名稱(chēng)為cache_one,內(nèi)存緩存空間大小為200MB,1天沒(méi)有被訪(fǎng)問(wèn)的內(nèi)容自動(dòng)清除,硬盤(pán)緩存空間大小為30GB。
- proxy_cache_path /data0/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
- location / {
- # 如果后端的服務(wù)器返回502、504、執(zhí)行超時(shí)等錯(cuò)誤,自動(dòng)將請(qǐng)求轉(zhuǎn)發(fā)到upstream負(fù)載均衡池中的另一臺(tái)服務(wù)器,實(shí)現(xiàn)故障轉(zhuǎn)移。
- proxy_next_upstream http_502 http_504 error timeout invalid_header;
- proxy_cache cache_one;
- # 對(duì)不同的HTTP狀態(tài)碼設(shè)置不同的緩存時(shí)間
- proxy_cache_valid 200 304 12h;
- # 以域名、URI、參數(shù)組合成Web緩存的Key值,Nginx根據(jù)Key值哈希,存儲(chǔ)緩存內(nèi)容到二級(jí)緩存目錄內(nèi)
- proxy_cache_key $host$uri$is_args$args;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_pass http://backend_server;
- expires 1d;
- }
- }
注1:Nginx反向代理緩存應(yīng)用于云閱讀縮略圖服務(wù)的緩存;
注2:Nginx仍舊以小文件的方式存儲(chǔ)緩存數(shù)據(jù),導(dǎo)致磁盤(pán)IOUtil較高,當(dāng)前線(xiàn)上使用SSD;
視頻播放
- server {
- # mp4后綴的文件走mp4播放模塊
- location ~ \.mp4$ {
- mp4;
- mp4_buffer_size 1m;
- mp4_max_buffer_size 5m;
- mp4_limit_rate on;
- mp4_limit_rate_after 30s;
- }
- # flv后綴的文件走flv播放模塊
- location ~ \.flv$ {
- flv;
- }
- }
注1:云課堂、公開(kāi)課就是使用這種方式進(jìn)行視頻播放;
注2:線(xiàn)上環(huán)境更加復(fù)雜,還編譯了第三方的mp4播放模塊以支持android4.4的播放;
常見(jiàn)問(wèn)題
- CLOUD-6824:與后端服務(wù)務(wù)必保持長(zhǎng)連接,否則將出現(xiàn)大量TIME_WAIT,并且會(huì)影響性能;
- CLOUD-6832:HTTP1.0的請(qǐng)求在過(guò)Nginx反向代理時(shí),默認(rèn)將不會(huì)保持Keep-Alive,需要專(zhuān)門(mén)進(jìn)行配置;
- CLOUD-6833:錯(cuò)誤日志error.log是監(jiān)控Nginx狀態(tài)的重要途徑,可以寫(xiě)腳本監(jiān)控其輸出并報(bào)警;
- CLOUD-6332:Nginx默認(rèn)會(huì)緩存上傳和下載的臨時(shí)文件,大量的上傳下載可能導(dǎo)致臨時(shí)文件目錄磁盤(pán)IO成為瓶頸,需要適當(dāng)調(diào)整;
- CLOUD-6519:Nginx與后端并發(fā)量不是很大的時(shí)候,可以開(kāi)啟流式下載,以避免臨時(shí)文件導(dǎo)致的額外磁盤(pán)IO;
- CLOUD-7493:Nginx讀靜態(tài)文件時(shí)默認(rèn)不會(huì)開(kāi)啟AIO,可能導(dǎo)致Worker進(jìn)程D狀態(tài);
- CLOUD-7065:Nginx默認(rèn)情況下,worker_rlimit_nofile為1024,導(dǎo)致大并發(fā)請(qǐng)求失敗,因此大并發(fā)需要設(shè)置合理的worker_rlimit_nofile值;
- CLOUD-6334:對(duì)于服務(wù)海量請(qǐng)求的Nginx,需要做專(zhuān)門(mén)的優(yōu)化,具體這里有專(zhuān)門(mén)的總結(jié);
- CLOUD-5582:Nginx與后端服務(wù)器Keep-Alive連接的數(shù)量為 worker_count * keep_alive 配置;
- CLOUD-7224:可以配置Nginx coredump時(shí)產(chǎn)生的core路徑,以便事后分析原因;
- CLOUD-7461:臨時(shí)文件緩存大小和后端連接的超時(shí)需要綜合考慮,否則可能出問(wèn)題;
- SDFS-497:如果后端服務(wù)返回的HTTP請(qǐng)求沒(méi)有Content-Length頭,Nginx默認(rèn)將使用Transfer-Encoding:chunked對(duì)Body進(jìn)行編碼;
#p#
Zookeeper:
ZooKeeper
一、簡(jiǎn)介
ZooKeeper是一個(gè)開(kāi)源的分布式應(yīng)用協(xié)調(diào)服務(wù),以Fast Paxos算法為理論基礎(chǔ),可保證分布式環(huán)境中數(shù)據(jù)的強(qiáng)一致性,可用于解決分布式應(yīng)用中經(jīng)常遇到的數(shù)據(jù)管理問(wèn)題。
二、ZooKeeper編程模型
ZooKeeper的數(shù)據(jù)模型風(fēng)格很像文件系統(tǒng)的目錄結(jié)構(gòu),可看做一個(gè)樹(shù)形結(jié)構(gòu)的數(shù)據(jù)庫(kù),與文件系統(tǒng)不同的是文件系統(tǒng)中的節(jié)點(diǎn)有目錄和文件的區(qū)分, 目錄是中間節(jié)點(diǎn),其本身并不存數(shù)據(jù),而文件是葉節(jié)點(diǎn),只有內(nèi)容沒(méi)有子項(xiàng);而zookeeper的樹(shù)形結(jié)構(gòu)中所有的節(jié)點(diǎn)上都能存儲(chǔ)數(shù)據(jù)內(nèi)容,也能包含子項(xiàng)。 其節(jié)點(diǎn)被成為zNode,zNode有臨時(shí)(EPHEMERAL)和遞增(SEQUENTIAL)等可選屬性,zNode可以通過(guò)配置Watcher來(lái)監(jiān) 控狀態(tài)變化,并引導(dǎo)客戶(hù)端觸發(fā)相應(yīng)操作。關(guān)于Zookeeper的介紹和數(shù)據(jù)模型等可參考以下文章:
http://shiyanjun.cn/archives/474.html
http://stblog.baidu-tech.com/?p=1164
三、應(yīng)用場(chǎng)景
常見(jiàn)的應(yīng)用場(chǎng)景如下:
場(chǎng)景1 心跳狀態(tài)檢測(cè)
利用zookeeper的EPHEMERAL節(jié)點(diǎn)的特征,記錄server的活動(dòng)狀態(tài)。server宕機(jī)時(shí),zookeeper連接斷開(kāi),EPHEMERAL自動(dòng)刪除,可通過(guò)watch EPHEMERAL節(jié)點(diǎn)的存在狀況判斷server的存活狀態(tài)。
場(chǎng)景2 全局自增ID的生成
利用Zookeeper的SEQUENTIAL的特征,單個(gè)節(jié)點(diǎn)下的SEQUENTIAL節(jié)點(diǎn)名稱(chēng)都帶有自增的序號(hào),獲取ID是只需創(chuàng)建一個(gè)SEQUENTIAL節(jié)點(diǎn)即可。
場(chǎng)景3 統(tǒng)一命名服務(wù)(Naming Service)
利用zk的樹(shù)形結(jié)構(gòu)特征,每個(gè)節(jié)點(diǎn)有全局唯一的路徑,可用來(lái)提供全局命名。
場(chǎng)景4 配置管理(即發(fā)布訂閱)
利用zookeeper可以配置Watcher的特征,可以將分布式系統(tǒng)的配置寫(xiě)入到不同的樹(shù)形節(jié)點(diǎn)中,客戶(hù)端對(duì)關(guān)心的配置項(xiàng)設(shè)置watcher,當(dāng)配置發(fā)生變更時(shí)自動(dòng)獲取最新配置,從而實(shí)現(xiàn)分布式環(huán)境下不同節(jié)點(diǎn)上配置的實(shí)時(shí)更新。
場(chǎng)景5 集群管理
利用zookeeper基于fast paxos算法的選舉功能,實(shí)現(xiàn)集群master節(jié)點(diǎn)的選舉??梢栽诩涵h(huán)境中master宕機(jī)時(shí)動(dòng)態(tài)選擇master,解決傳統(tǒng)上很容易出現(xiàn)的單點(diǎn)故障問(wèn)題。
場(chǎng)景6 共享鎖Locks
利用EPHEMERAL_SEQUENTIAL節(jié)點(diǎn)的特征,實(shí)現(xiàn)共享鎖,需要獲得鎖的 Server 創(chuàng)建一個(gè) EPHEMERAL_SEQUENTIAL 目錄節(jié)點(diǎn),然后調(diào)用 getChildren方法獲取當(dāng)前的目錄節(jié)點(diǎn)列表中最小的目錄節(jié)點(diǎn)是不是就是自己創(chuàng)建的目錄節(jié)點(diǎn),如果正是自己創(chuàng)建的,那么它就獲得了這個(gè)鎖,如果不是 那么它就調(diào)用 exists(String path, boolean watch) 方法并監(jiān)控 Zookeeper 上目錄節(jié)點(diǎn)列表的變化,一直到自己創(chuàng)建的節(jié)點(diǎn)是列表中最小編號(hào)的目錄節(jié)點(diǎn),從而獲得鎖,釋放鎖時(shí)直接刪除自己創(chuàng)建的節(jié)點(diǎn)。
場(chǎng)景7 隊(duì)列管理
ZooKeeper 可以處理兩種類(lèi)型的隊(duì)列:
1. 當(dāng)一個(gè)隊(duì)列的成員都聚齊時(shí),這個(gè)隊(duì)列才可用,否則一直等待所有成員到達(dá),這種是同步隊(duì)列。
2. 隊(duì)列按照 FIFO 方式進(jìn)行入隊(duì)和出隊(duì)操作,例如實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者模型。關(guān)于應(yīng)用場(chǎng)景的描述和實(shí)現(xiàn)具體可參考以下博文:
http://django-china.cn/topic/135/ (原文http://rdc.taobao.com/team/jm/archives/1232 )
四、應(yīng)用陷阱
并不是任何分布式應(yīng)用都適合使用ZooKeeper來(lái)構(gòu)建協(xié)調(diào)服務(wù),以下是幾種可能出現(xiàn)的問(wèn)題:
1. 丟失ZNode上的變更通知
客戶(hù)端連接到ZooKeeper Server以后,會(huì)維護(hù)一個(gè)TCP連接,在CONNECTED狀態(tài)下,客戶(hù)端設(shè)置了某個(gè)ZNode的Watch監(jiān)聽(tīng)器,可以收到來(lái)自該節(jié)點(diǎn)變更的通知并 觸發(fā)相應(yīng)的事件。但是如果由于網(wǎng)絡(luò)異常客戶(hù)端斷開(kāi)了與ZooKeeper Server的連接,在斷開(kāi)的過(guò)程中,是無(wú)法收到ZooKeeper在ZNode上發(fā)送的節(jié)點(diǎn)數(shù)據(jù)變更通知的。如果使用ZooKeeper的Watch, 必須要尋找保持CONNECTED的Watch,才能保證不會(huì)丟失該Watch監(jiān)控的ZNode上的數(shù)據(jù)變更通知。
2. 無(wú)效ZooKeeper集群節(jié)點(diǎn)列表
與ZooKeeper集群交互時(shí),一般情況下客戶(hù)端會(huì)持有一個(gè)ZooKeeper集群節(jié)點(diǎn)的列表,或者列表的子集,那么會(huì)存在如下兩種情況: 一種情況是,如果客戶(hù)端持有ZooKeeper集群節(jié)點(diǎn)列表或列表子集,如果列表中的某些節(jié)點(diǎn)因?yàn)楣收贤顺隽思嚎蛻?hù)端再次連接這一類(lèi)失效的節(jié)點(diǎn),就無(wú)法 獲取服務(wù)。所以在應(yīng)用中使用ZooKeeper集群時(shí),一定要明確這一點(diǎn),或者跳過(guò)無(wú)效的節(jié)點(diǎn),或者重新尋找有效的節(jié)點(diǎn)繼續(xù)業(yè)務(wù)處理,或者檢查 ZooKeeper集群,使整個(gè)集群恢復(fù)正常。
3. 配置導(dǎo)致的性能問(wèn)題
如果設(shè)置Java堆內(nèi)存(Heap)不合理,會(huì)導(dǎo)致ZooKeeper內(nèi)存不足,會(huì)在內(nèi)存與文件系統(tǒng)之間進(jìn)行數(shù)據(jù)交換,導(dǎo)致ZooKeeper的性 能極大地下降,從而可能會(huì)影響應(yīng)用程序。為了避免Swapping問(wèn)題的出現(xiàn),主要考慮設(shè)置足夠的Java堆內(nèi)存,同時(shí)減少被操作系統(tǒng)和Cache使用的 內(nèi)存,盡量避免在內(nèi)存與文件系統(tǒng)之間發(fā)生數(shù)據(jù)交換,或者可以將交換限制在一定的范圍之內(nèi)。
4. 事務(wù)日志存儲(chǔ)設(shè)備性能
ZooKeeper會(huì)同步事務(wù)到存儲(chǔ)設(shè)備,如果存儲(chǔ)設(shè)備不是專(zhuān)用的,而是和其他I/O密集型應(yīng)用共享同一磁盤(pán),會(huì)導(dǎo)致ZooKeeper的效率降 低。因?yàn)榭蛻?hù)端請(qǐng)求ZNode數(shù)據(jù)變更而發(fā)生的事務(wù),ZooKeeper會(huì)在響應(yīng)之前將事務(wù)日志寫(xiě)入存儲(chǔ)設(shè)備,為zookeeper配置專(zhuān)用的存儲(chǔ)設(shè)備可 以使整個(gè)服務(wù)以及外部應(yīng)用都會(huì)獲得極大地性能提升。
5. ZNode存儲(chǔ)大量數(shù)據(jù)導(dǎo)致性能問(wèn)題
ZooKeeper的設(shè)計(jì)初衷是,每個(gè)ZNode只存放少量的同步數(shù)據(jù)(一般一個(gè)節(jié)點(diǎn)上的數(shù)據(jù)小于1M),如果存儲(chǔ)了大量數(shù)據(jù),導(dǎo)致 ZooKeeper每次節(jié)點(diǎn)發(fā)生變更時(shí)需要將事務(wù)寫(xiě)入存儲(chǔ)設(shè)備,同時(shí)還要在集群內(nèi)部復(fù)制傳播,這將導(dǎo)致不可避免的延遲和性能問(wèn)題。所以,如果需要與大量的 數(shù)據(jù)相關(guān),可以將大量數(shù)據(jù)存儲(chǔ)在其他設(shè)備中,而只是在ZooKeeper中存儲(chǔ)一個(gè)簡(jiǎn)單的映射,如指針、引用等等。
五、其他
- zookeeper節(jié)點(diǎn)的size限制,和超限后的解決方法
Zookeeper單個(gè)Znode能存放的數(shù)據(jù)大小在1M左右,如果數(shù)據(jù)量過(guò)大客戶(hù)端會(huì)出現(xiàn)異常,異常信息類(lèi)似如下:Packet len5187750 is out of range!
這種情況可以通過(guò)修改java環(huán)境變量來(lái)解決,但是還是需要在應(yīng)用中避免在zookeeper上存儲(chǔ)大量數(shù)據(jù)的情況,這是一種不好的使用方式。-Djute.maxbuffer=51877500
如:$JAVA -cp “$CLASSPATH” -Djute.maxbuffer=51877500 com.netease.datastream.tool.zkUtil.opers.ZkUtilMain $* 2>&1 &
- 配置完ZooKeeper集群服務(wù)之后要配置Snapshot和Transaction log的定時(shí)清理任務(wù)
由于所有zookeeper上的數(shù)據(jù)操作都會(huì)觸發(fā)事務(wù)日志,事務(wù)日志在達(dá)到一定大小之后會(huì)歸檔為鏡像文件snapshot,如果不配置定時(shí)清理任務(wù),這些文件會(huì)很快耗盡磁盤(pán)空間??梢栽趌inux的crontab任務(wù)列表中配置如下項(xiàng):# m h dom mon dow command
0 7 * * * /home/ds/zookeeper/bin/zkCleanup.sh -n 5 >/dev/null以上任務(wù)表示每日7:00執(zhí)行清理任務(wù),僅保留最新的5個(gè)鏡像文件和事務(wù)日志。
- 查看指定某個(gè)節(jié)點(diǎn)狀態(tài)
可通過(guò)以下腳本echo stat|nc
- 相關(guān)工具
Eclipse插件 update-site http://www.massedynamic.org/eclipse/updates/
Zookeeper瀏覽器客戶(hù)端 https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip
附、參考文檔
官方文檔: http://zookeeper.apache.org/doc/r3.4.5/
安裝配置: http://shiyanjun.cn/archives/469.html
網(wǎng)站標(biāo)題:那些分布式系統(tǒng)設(shè)計(jì)常用的開(kāi)源模塊
網(wǎng)址分享:http://fisionsoft.com.cn/article/ccoiopo.html


咨詢(xún)
建站咨詢(xún)
