1. HBase有合適的SQL層嗎?
單機(jī)kv基礎(chǔ)上做分布式kv再做SQL計算,為什么不在已有的HBase基礎(chǔ)上再做SQL層呢?
無論在單機(jī)kv之上棍郎,還是在分布式kv,增加SQL層银室,從目前的涌現(xiàn)出的技術(shù)棧來看并不是難事涂佃,例如:Hive,Impla蜈敢,Presto和Spark SQL辜荠。
另外你提出:為什么沒有基于HBase之上的SQL層?這是錯誤的觀點抓狭,上述SQL引擎都可以作為HBase的SQL層伯病。
但是作為關(guān)系型數(shù)據(jù)庫,支持多表事務(wù)否过,的確基于HBase沒有很好的解決方案午笛。
首先目前HBase的事務(wù)是針對單機(jī)Region Server的單表行級事務(wù),也就是客戶端一次請求苗桂,會將多筆記錄作為一條日志針對一個Region進(jìn)行處理药磺,成功則寫入MemStore,失敗則WAL回滾誉察,所以事務(wù)操作并不復(fù)雜与涡,但是若要在一次事務(wù)中實現(xiàn)多表寫入,多機(jī)Region一致性協(xié)同,這在HBase設(shè)計之初并沒有考慮驼卖。
因此氨肌,若按照目前HBase的設(shè)計,寫入不同HRegionServer酌畜,再寫入不同Region的MemStore記錄怎囚,包括各個WAL的記錄,必須保證一致性桥胞,這就是Region分布式一致性的第一難恳守,必須要有集群一致性機(jī)制,例如PaxOS或者Raft贩虾,可是HBase沒有催烘,只有一個簡單的Master解決Region分片后的遷移平衡問題。必須要具備表表之間缎罢,列簇之間的ACID特性伊群,HBase并沒有設(shè)計此處,他的Master和Region?Server在這些問題上基本沒有任何前期預(yù)留的分布式擴(kuò)展機(jī)制策精。
其次每次事務(wù)必然會有多次查詢請求舰始,如果用TPS代表事務(wù)吞吐,那么QPS就代表了一次TPS內(nèi)可能涉及數(shù)百次的查詢咽袜,我們可以忍受1秒1個事務(wù)操作丸卷,但是查詢不行,每次查詢必須能在毫秒內(nèi)完成询刹,甚至更短周期谜嫉,那么這就存在優(yōu)化問題了,如果查詢是熱點數(shù)據(jù)在MemStore或者BlockCache中范抓,這還好說骄恶,但是在多個HFile的磁盤中掃描這就慢了,例如:HBase的LSM-Tree的刪除和更新都只是一條新記錄的標(biāo)識匕垫,這種用空間換取寫入性能的設(shè)計,另外的副作用就是增加查詢量虐呻,過期數(shù)據(jù)在查詢中都掃描出來象泵,由掃描器自己去過濾。那么為了解決查詢問題斟叼,就必須加大內(nèi)存和使用固態(tài)磁盤來解決查詢速度偶惠,這就是第二難,實際上HBase類LSM樹的查詢機(jī)制復(fù)雜度遠(yuǎn)高于寫入朗涩,而且提升基礎(chǔ)資源成本改善性能并不具有普適性忽孽,這就是另一個問題了!
或許LevelDB,Rocksdb兄一,這些輕量級的kv的查詢性能比起HBase會更適合事務(wù)單元內(nèi)的高密度kv查詢厘线,但HBase還是傾向于大吞吐kv寫入和熱點數(shù)據(jù)查詢用于支撐實時流處理過程的流庫連接。因此我認(rèn)為HBase要是考慮在未來支持分布式RDBMS出革,必須得徹底升級Master服務(wù)支撐Region?Server的分布式一致性造壮,并且實現(xiàn)跨表的ACID特性支持,最后就是Region級別的讀優(yōu)化骂束。
2. HBase適合大規(guī)模數(shù)據(jù)查詢嗎耳璧?
10億左右的數(shù)據(jù)量,Mongodb可以勝任嗎展箱,還是說需要使用HBase這種數(shù)據(jù)庫旨枯,我主要是對查詢速度有點要求,大部分查詢都是模糊查詢混驰,對一個很長的字符串召廷,找到與目標(biāo)關(guān)鍵詞匹配的的一句話,另外我用的語言是node账胧,感覺不知道怎么選竞慢?
如果你的主要需求是查詢,那么HBase顯然不符合你的需求治泥,因為HBase擅長于寫多讀少的場景筹煮,它的Region結(jié)構(gòu)主要是面向列簇在Memstore中也就是內(nèi)存中緩沖寫入的近期數(shù)據(jù),然后定期定量刷新到磁盤上居夹,這種機(jī)制非常有利于高速寫入败潦,在查詢上查詢近期熱點數(shù)據(jù)的優(yōu)勢很明顯,從Memstore中查詢近期數(shù)據(jù)准脂,從專門用于緩存的BlockCache中劫扒,查詢熱點數(shù)據(jù),因為它基于LRU機(jī)制狸膏。
但是作為模糊查詢這就有問題了沟饥,模糊查詢的效率關(guān)鍵在于二級索引,但是HBase的設(shè)計主要是通過行鍵實現(xiàn)列簇下湾戳,面向一級索引的LSM-Tree結(jié)構(gòu)贤旷,配合布隆過濾器,實現(xiàn)高效的數(shù)據(jù)掃描匹配砾脑。模糊查詢往往需要借助Mr或者Spark計算引擎來實現(xiàn)幼驶,因此非常不適合模糊查詢的需求。
相比較下韧衣,MongoDB更適合你的需求盅藻,它具有和傳統(tǒng)數(shù)據(jù)庫一樣的购桑,構(gòu)建在B樹索引之上,具有成熟的字段二級索引氏淑,非常適合模糊查找勃蜘,但是MongoDB對于集合join關(guān)聯(lián)查詢并不行,往往需要文檔嵌套結(jié)構(gòu)或者多次文檔查找來解決夸政,因此關(guān)鍵看你的需求這種文檔關(guān)聯(lián)的查詢是否多元旬,如果不是很復(fù)雜的關(guān)聯(lián),那么MongoDB的集合分片shard可以更好的對十億級數(shù)據(jù)集合進(jìn)行切分守问,分布在不同的副本節(jié)點上匀归,通過路由器實現(xiàn)多點查詢,單點聚合耗帕,那么十億級數(shù)據(jù)的模糊查找問題不算大穆端。
關(guān)鍵是看MongoDB關(guān)聯(lián)操作的復(fù)雜性有多大,是否影響查詢效率仿便。要是特別復(fù)雜的業(yè)務(wù)關(guān)聯(lián)查找体啰,最好考慮優(yōu)化MySQL分區(qū)或者PostgreSQL并行這種單機(jī)模式是否能快速查詢解決,或許查詢效果會更好嗽仪,再或者考慮TiDB這種分布式關(guān)系數(shù)據(jù)庫來解決荒勇。
3. HBase是如何保證緩存與文件的寫入一致性?
高并發(fā)場景下闻坚,怎么保證緩存和數(shù)據(jù)庫的數(shù)據(jù)一致性沽翔?具體解決方案是什么?有哪些框架窿凤?具體怎么實現(xiàn)仅偎?
你的問題我認(rèn)為特別符合HBase的特性。從一致性角度根子上不適合MySQL+Redis的組合模式雳殊。
首先我們說數(shù)據(jù)庫針對高并發(fā)的場景最有效的手段:有效緩存和并行性橘沥,有效緩存就是客戶端實時、持續(xù)的讀寫都可以在緩存中完成和命中夯秃,那么就不需要依賴磁盤I/O座咆,沒有磁盤的約束,就可以提升數(shù)據(jù)服務(wù)的吞吐量寝并,這一點對于數(shù)據(jù)讀寫并發(fā)非常重要箫措。
其次就是并行性,并行處理我們可以在單臺多核完成衬潦,也可以在多臺分布式完成,當(dāng)內(nèi)存有邊界的情況下植酥,當(dāng)然通過分布式形成多個業(yè)務(wù)表的并行讀寫镀岛,這樣針對大量并發(fā)產(chǎn)生的內(nèi)存存量弦牡,效果肯定是最好的。
那么我們回到開頭看提出的答案HBase漂羊。它的內(nèi)部針對寫入數(shù)據(jù)主要是MemStore來緩存驾锰,另外WAL負(fù)責(zé)順序記錄寫入日志,作為寫入過程中出現(xiàn)內(nèi)存數(shù)據(jù)丟失的數(shù)據(jù)恢復(fù)走越,由于WAL是順序?qū)懭際DFS椭豫,其磁盤I/O性能是遠(yuǎn)遠(yuǎn)勝于索引結(jié)構(gòu)的數(shù)據(jù)表,可以承載更大限度的數(shù)據(jù)吞吐旨指。
如果是高并發(fā)的讀寫赏酥,就近時間形成的熱點數(shù)據(jù)的讀寫場景會很常見,HBase基本上在一個Region滿128M內(nèi)存存量之前都可以在MemStore緩存中完成最近數(shù)據(jù)的讀寫谆构。如果不是最近數(shù)據(jù)裸扶,但仍是頻繁訪問的熱點數(shù)據(jù),那么由另外一組緩存BlockCache基于LRU算法專門提供熱點數(shù)據(jù)的查詢搬素。因此針對高并發(fā)呵晨,我認(rèn)為HBase是滿足就近和熱點數(shù)據(jù)實時與高并發(fā)的讀寫。
但是一定注意時間跨度大熬尺,又極為隨機(jī)的查詢摸屠,并不適應(yīng)HBase,因為HBase是基于LSM-Tree和SSTable粱哼,層層疊加的數(shù)據(jù)排序文件季二,并不適合跨大范圍的隨機(jī)掃描查找。
再就是并行性皂吮,HBase通過分布式形成HRegionserver集群戒傻,數(shù)據(jù)表被切分成Region,類似于自動對MySQL進(jìn)行了分庫分表蜂筹,那么對每個范圍的Region數(shù)據(jù)進(jìn)行讀取就能通過HRegionServer來分解單表的壓力需纳。若業(yè)務(wù)表很多,分解在不同的HRegionserver來支持各自表的讀寫艺挪,肯定比放在單機(jī)要好的多不翩!
我們再說一致性,只要提到高并發(fā)的緩存系統(tǒng)我們往往想到了Redis+MySQL的組合套裝來解決麻裳,通過Redis來防止MySQL穿透口蝠,可是問題在于Redis和MySQL的數(shù)據(jù)復(fù)制,是建立在記錄的異步傳輸過程津坑,如果采用程序打成強(qiáng)制性同步妙蔗,那么就等于Redis拖著MySQL走,這種情況不如不用Redis疆瑰,所以理想的一致性是達(dá)不到的眉反,但是對于秒殺昙啄,搶票這些場景,異步延時這是無法忍受的寸五,會產(chǎn)生嚴(yán)重的業(yè)務(wù)數(shù)據(jù)的錯亂梳凛。
但是HBase就不同了,它的一次寫更新事務(wù)一定是在一個HRegionserver上的一個Region上的一組行級數(shù)據(jù)提交梳杏,不存在一次寫過程的異步傳輸韧拒,也就說如果你能將業(yè)務(wù)的一次讀寫控制在行級事務(wù)范圍,完全可以考慮使用HBase來解決一致性十性,也就是用簡化的業(yè)務(wù)模型來交換高性能寫吞吐兼?zhèn)鋽?shù)據(jù)一致性叛溢,等承載完業(yè)務(wù)的實時部分之后,再異步的將結(jié)果從HBase中取出烁试,慢慢形成復(fù)雜的關(guān)系模型這個思路雇初。
HBase之所以能形成緩存和磁盤I/O的一致性,就是因為面向Region的StoreFile(也就是Hadoop HDFS的HFile)并不直接參與事務(wù)减响,所有事務(wù)都是在MemStore和WAL中配合完成靖诗,而且memstore與StoreFile的Flush不是針對一條記錄的,而是針對一次128m或者定時刷新MemStore數(shù)據(jù)量支示,在Flush的過程中刊橘,HBase會保證一致性,這時候會存在短暫的刷盤導(dǎo)致的寫請求堵塞颂鸿,但是只有這樣促绵,才能從大吞吐的角度照顧到大多數(shù)時間的高速寫入緩存,以及保證緩存向磁盤持久化過程的一致性嘴纺!
4. 全局唯一ID在分布式系統(tǒng)中用來做什么用败晴?
這個全局唯一ID用到哪些場景中呢? 為什么有些公司 還要單門的 有服務(wù)器 提供生成全局ID的服務(wù)呢栽渴?使用UUID不行嗎尖坤?想不通為什么要寫一個單門的功能。unique id 到底有哪些用途闲擦?
我就拿HBase給你舉個例子吧慢味。
HBase是分布式數(shù)據(jù)庫,由多臺regionserver組成的集群存儲許多region墅冷,每個region我們可以理解成數(shù)據(jù)表(列簇)的一個切片纯路。
我們對HBase的數(shù)據(jù)表(列簇)理解為一張Excel表,Excel表的特點就是列可以非常寬寞忿,我們稱之為寬表驰唬,而且不同行的某些列值可有可無,這就形成了稀疏表腔彰。
表行列如Excel般靈活定嗓,那么HBase作為數(shù)據(jù)庫是如何做到的呢蜕琴?它實際上是存儲了一個個獨立且原子級別的單元格萍桌,就是K/V存儲單元宵溅,不同K/V之間并沒有類似關(guān)系型數(shù)據(jù)庫的主外鍵關(guān)聯(lián),這樣就保證了足夠的靈活性的基礎(chǔ)上炎。
好恃逻,現(xiàn)在談到關(guān)鍵問題,HBase是怎么讓K/V形成行列的邏輯上的關(guān)聯(lián)形式呢藕施?答案就在于K/V中的主鍵寇损,這就是題主所疑惑的分布式系統(tǒng)為什么還要用獨立設(shè)計的主鍵而不是UUID,原因就在于獨立設(shè)計的主鍵是有語義的裳食!
主鍵由行鍵矛市、列簇名、列名诲祸、時間戳等組成了分布式數(shù)據(jù)庫的唯一主鍵浊吏,HBase基于自己的region寫入機(jī)制和分片機(jī)制,始終保持了表(列簇)的K/V單元在所有regionserver上按照主鍵順序的救氯,有范圍的region存放找田。
這種順序規(guī)則就是對主鍵逐次排序:行鍵排序->列簇名排序->列名排序->時間戳排序,大家看到?jīng)]有着憨,就是這么一個排序策略墩衙,就非常容易的讓查詢按行鍵(一行)過濾需要的K/V,再按列簇過濾甲抖,那么就拿到了一行多列了漆改,而且每一列可能還有多個歷史K/V(通過時間戳已經(jīng)排序)。
看到了嗎准谚?優(yōu)秀的主鍵設(shè)計的威力就是這么強(qiáng)氛魁,無論你的數(shù)據(jù)在哪臺服務(wù)節(jié)點上秀存,主鍵來解釋你的數(shù)據(jù)屬于整體上的哪個位置。
5. HBase 的原理更像是Mysql 讀寫分離還是分庫分表祈纯?
此時有10000個客戶端在一瞬間同時發(fā)起 10000次寫 write 請求(共一億)粒没,那這一億個請求在同一時刻是發(fā)給“十個 slave 中的某一個 server” (一個有難,九個圍觀)還是分給“十個slave server 一起來處理”(有難同當(dāng))入蛆?
首先要確定這10000客戶端是不是朝一個列簇寫?若不是一個列簇想幻,那么就相當(dāng)于給多個列簇下的region寫數(shù)據(jù)。那么就可能涉及多臺server參與寫數(shù)據(jù)。
在同一時刻,每個列簇只會有一個region服務(wù)于寫入率挣。
核心機(jī)制是:一個region在寫得足夠大智什,超過設(shè)定閾值后就會拆分(split)荠锭,拆分后的region會分配到新的sever删豺,不斷拆分呀页,會逐漸將其他9個server都分配到region赔桌。
但是拆分的region是按照行鍵順序進(jìn)行排列的,對于region分布滿十臺server的列簇來講雪位,在這種情況下,始終會是一個server負(fù)責(zé)寫進(jìn)region港粱,這十個server會根據(jù)自己的行鍵范圍負(fù)責(zé)讀寸宏。
因此對于多個列簇,正好不同列簇中負(fù)責(zé)支撐寫入的region分布在不同的server上偿曙,那么這就類似于分庫分表氮凝。
對于一個列簇中多個被拆分的region,分布在不同的server上望忆,那么只有一個region支撐寫罩阵,所有的region支撐不同行鍵范圍的讀,因此就類似于讀寫分離启摄。