在HBase中暮芭,表格的Rowkey按照字典排序,Region按照RowKey設(shè)置split point進(jìn)行shard窖剑,通過這種方式實(shí)現(xiàn)的全局斗蒋、分布式索引淮野,成為了其成功的最大的砝碼捧书。圖1顯示了HBase表格的Rowkey切分與Region的部署關(guān)系圖。
圖1: HBase Rowkey-Region 關(guān)系圖
然而骤星,隨著在HBase系統(tǒng)上應(yīng)用的驅(qū)動(dòng),人們發(fā)現(xiàn)Global-Rowkey-Indexing不再滿足應(yīng)用的需求爆哑。單一的通過Rowkey檢索數(shù)據(jù)的方式洞难,不再滿足更多應(yīng)用的需求,人們希望像SQL一樣檢索數(shù)據(jù)揭朝,select * from table where col=val队贱。可是潭袱,HBase之前的定位是大表的存儲(chǔ)柱嫌,要進(jìn)行這樣的查詢,往往是要通過類似Hive屯换、Pig等系統(tǒng)進(jìn)行全表的MapReduce計(jì)算编丘,這種方式既浪費(fèi)了機(jī)器的計(jì)算資源,又因高延遲使得應(yīng)用黯然失色彤悔。于是嘉抓,在業(yè)界和社區(qū),針對(duì)HBase Secondary Indexing的方案晕窑,成為HBase新版本(0.96)呼聲最高的一項(xiàng)Feature抑片。
粗略分析了當(dāng)前的技術(shù),大概的方案可以總結(jié)為這樣兩類:
1杨赤、使用HBase的coprocessor敞斋。CoProcessor相當(dāng)于HBase的Observer+hook,目前支持MasterObserver疾牲、RegionObserver和WALObserver植捎,基本上對(duì)于HBase Table的管理、數(shù)據(jù)的Put说敏、Delete鸥跟、Get等操作都可以找到對(duì)應(yīng)的pre和post。這樣如果需要對(duì)于某一項(xiàng)Column建立Secondary Indexing盔沫,就可以在Put医咨、Delete的時(shí)候,將其信息更新到另外一張索引表中架诞。如圖二所示拟淮,對(duì)于Indexing里面的value值是否存儲(chǔ)的問題,可以根據(jù)需要進(jìn)行控制谴忧,如果value的空間開銷不大很泊,逆向的檢索又比較頻繁角虫,可以直接存儲(chǔ)在Indexing Table中,反之則避免這種情況委造。
圖2 使用HBase Coprocessor實(shí)現(xiàn)Secondary Indexing
2戳鹅、由客戶端發(fā)起對(duì)于主表和索引表的Put、Delete操作的雙重操作昏兆。源自:http://hadoop-hbase.blogspot.com/2012/10/musings-on-secondary-indexes.html 【墻外】
它具體的做法總結(jié)起來有:
設(shè)置主表的TTL(Time To Live)比索引表小一點(diǎn)枫虏,讓其略早一點(diǎn)消亡。
不要在IndexingTable存儲(chǔ)Value值爬虱,即刪除如圖2所示的val列隶债。
Put操作時(shí),對(duì)于操作的主表的所有列跑筝,使用同一的Local TimeStamp的值死讹,更新到Indexing Table,然后使用該TimeStamp插入主表數(shù)據(jù)曲梗。
Delete操作時(shí)赞警,首先操作主表的數(shù)據(jù),然后再去更新Indexing Table的數(shù)據(jù)稀并。
雖然在這種方案里無法保證原子性和一致性仅颇,但是通過TimeStamp的設(shè)置,No Locks和 No Server-side codes碘举,使其在二級(jí)索引上有著較大的優(yōu)勢(shì)忘瓦。至于中間出錯(cuò)的環(huán)節(jié),我們看看是否可以容忍:
1)Put索引表成功引颈,Put主表失敗耕皮。由于Indexing Table不存儲(chǔ)val值,仍需要跳轉(zhuǎn)到Main Table,所以這樣的錯(cuò)誤相當(dāng)于拿一個(gè)Stale index去訪問對(duì)應(yīng)Rowkey吧了蝙场,對(duì)結(jié)果正確性沒有影響凌停。
2)Delete主表成功,Delete索引表失敗售滤。都是索引表的內(nèi)容>=主表的內(nèi)容而已罚拟,而實(shí)際返回值需要通過主表進(jìn)行。
生產(chǎn)環(huán)境下完箩,什么樣的方法實(shí)用性更強(qiáng)赐俗?
就這個(gè)問題,根據(jù)個(gè)人當(dāng)前對(duì)于生產(chǎn)環(huán)境下HBase集群的經(jīng)驗(yàn)弊知,綜合上面兩種方式的優(yōu)劣阻逮,可以通過這樣的方式設(shè)計(jì)。
1秩彤、主表服務(wù)在線業(yè)務(wù)叔扼,它的性能需要保證事哭。使用coprocessor和客戶端的封裝也好,都會(huì)影響其性能瓜富,所以在正常情況下鳍咱,直接操作都不太合適。如果想使用方案二食呻,我倒是感覺流炕,可以調(diào)整Indexing Table的操作方式,去除保證其安全性的內(nèi)容仅胞,比如可以關(guān)閉寫HLOG,這樣會(huì)進(jìn)一步減低其操作的延遲剑辫。
2干旧、離線更新索引表。在真正需要二級(jí)索引的場(chǎng)景內(nèi)妹蔽,其時(shí)效性要求往往不高椎眯。可以將索引實(shí)時(shí)更新到Redis等KV系統(tǒng)中胳岂,定時(shí)從KV更新索引到Hbase的Indexing Table中编整。PS:Redis里面有DB設(shè)置的概念,可以按照時(shí)間段進(jìn)行隔離乳丰,這樣某段時(shí)間內(nèi)的數(shù)據(jù)會(huì)更新到Redis上掌测,保證Redis導(dǎo)入MapReduce之后仍然可以進(jìn)行update操作。
PS:社區(qū)和生產(chǎn)系統(tǒng)關(guān)于Hbase二級(jí)索引的方案产园,還在繼續(xù)當(dāng)中汞斧,會(huì)持續(xù)關(guān)注。