一诈嘿、存儲模式
1.1 行式存儲&列式存儲
定義
以行為存儲基準(zhǔn)的存儲方式稱為行式存儲免胃,一行的數(shù)據(jù)聚合存儲在一塊;
以列為存儲基準(zhǔn)的存儲方式稱為列式存儲蛙奖,保證每一列的數(shù)據(jù)存儲在一塊。
特點(diǎn)
行式存儲:維護(hù)大量的索引杆兵,存儲的成本比較高雁仲。不能夠做到線性擴(kuò)展,由于維護(hù)的大量索引使得其隨機(jī)讀的效率很高琐脏。另外攒砖,對于事務(wù)的處理有很好的支持。
列式存儲:根據(jù)同一列數(shù)據(jù)的相似性原理日裙,有利于對數(shù)據(jù)進(jìn)行壓縮吹艇,其壓縮效率遠(yuǎn)高于行式存儲,存儲成本比較低昂拂。另外受神,對于查詢多個列的數(shù)據(jù),可以利用并行計算提高效率格侯。
應(yīng)用場景
對于單列或者相對比例較少的列并且獲取頻率較高鼻听,特別對于大數(shù)據(jù)的環(huán)境,需要使用到數(shù)據(jù)壓縮和并行計算养交,就可以選擇列式存儲精算;
當(dāng)表和表之間存在很多關(guān)聯(lián)關(guān)系并且數(shù)據(jù)量不大瓢宦,可以選擇使用行式存儲碎连,其最大優(yōu)勢就是其事務(wù)處理的能力。
1.2 HBase列族式存儲
列族就是指多個數(shù)據(jù)列的組合驮履,HBase中的每個列都?xì)w屬于一個列族鱼辙,列族是表schema的一部分,但列并不是的玫镐。訪問控制倒戏、磁盤和內(nèi)存的使用統(tǒng)計都是在列族層面進(jìn)行的。每個列族中的列是經(jīng)常需要一起訪問的恐似,這樣才會使得數(shù)據(jù)存取的最優(yōu)性杜跷。
HBase Table的組成:
Table=RowKey(行鍵)+Family(列族)+Column(列)+Timestamp(版本或時間戳)+Value(值)
數(shù)據(jù)存儲模式(K-V):
(RowKey,F(xiàn)amily矫夷,Column葛闷,Timestamp) -> Value
列數(shù)據(jù)屬性:
HBase中默認(rèn)一列數(shù)據(jù)可以保存三個版本,特別對于聊天數(shù)據(jù)双藕,標(biāo)記已讀淑趾、未讀等屬性。
數(shù)據(jù)存儲原型:
按照RowKey忧陪、Column扣泊、Value近范、Timestamp的順序按字典序排序:
?
?
二、數(shù)據(jù)表解析
2.1 建表語句解析
示例建表語句:
create 'demo:user',
{NAME=>'b',VERSIONS=>'3',COMPERSSION=>'SNAPPY',COMPRESSION_COMPACT=>'SNAPPY',
REPLICATION_SCOPE=>1},
{NAME=>'o',REPLICATION_SCOPE=>1,COMPERSSION=>'SNAPPY',COMPRESSION_COMPACT=>'SNAPPY'}
NAME:列族名延蟹,必填項评矩;
VERSION:數(shù)據(jù)版本,設(shè)置一列的數(shù)據(jù)版本數(shù)量阱飘;
REPLICATION_SCOPE:復(fù)制機(jī)制稚照,主從復(fù)制。通過預(yù)寫日志和Hlog實(shí)現(xiàn)的俯萌,當(dāng)請求發(fā)送給Master的時候果录,log日志放入hdfs的同時,會進(jìn)入REPLICATION這個隊列中咐熙,通由Slave通過Zookeeper去獲取弱恒,并寫入Slave中的表;
COMPERSSION:數(shù)據(jù)壓縮的配置棋恼。
Snappy:是一種壓縮特性返弹,其編解碼速率更高
2.2 數(shù)據(jù)存儲目錄解析
在hbase-site.xml文件中設(shè)置數(shù)據(jù)存儲目錄:
<property>
<name>hbase.rootdir</name>
<value>/home/hbase_data</value>
</property>
.tmp:當(dāng)對表進(jìn)行創(chuàng)建和刪除操作的時候,會將表移動到該目錄下爪飘,然后再進(jìn)行操作义起。它是一個臨時存儲當(dāng)前需要修改的數(shù)據(jù)結(jié)構(gòu)。
WALs:存儲預(yù)寫日志师崎。
archive:存儲表的歸檔和快照默终,由Master上的一個任務(wù)定時進(jìn)行處理。
corrupt:用于存儲損壞的日志文件犁罩,一般為空齐蔽。
data:存儲數(shù)據(jù)的核心目錄,系統(tǒng)表和用戶表均存儲在這個目錄下床估。
hbase.id:hbase:集群中的唯一id含滴,用于標(biāo)識hbase進(jìn)程。
hbase.version:表明了文件版本信息丐巫。
oldWALs:當(dāng)log已經(jīng)持久化以后谈况,WALs中的日志文件會移動到該目錄下。
?
?
2.3 元信息表(系統(tǒng)表)
元信息表同樣是一張hbase表递胧,同樣擁有RowKey和列族這樣的概念碑韵。存儲在region server上,位于zookeeper上谓着,用戶查詢數(shù)據(jù)的時候泼诱,需要先到zookeeper上獲取到meta表的region server的地址再到到相應(yīng)region server上進(jìn)行查找,如下圖所示:
?
?
RowKey:格式化的region key
value:保存著region server的地址赊锚,其中最重要的一個列族就是info治筒,其中最重要的數(shù)據(jù)列是server屉栓,包含region server的地址和端口號。
元信息表的值當(dāng)region進(jìn)行分割耸袜、disable友多、enable、drop或balance等操作堤框,或region server掛掉都會導(dǎo)致元信息表值的變化域滥,Master就需要重新分配region,元信息表就會及時更新蜈抓。元信息表相當(dāng)于hbase的第一級索引启绰,是hbase中最重要的系統(tǒng)表。
三沟使、存儲設(shè)計
3.1 HBase中的LSM存儲思想
LSM樹(Log-Structured Merge-Trees):日志結(jié)構(gòu)合并樹委可,由兩個或兩個以上存儲數(shù)據(jù)的結(jié)構(gòu)組成的,每一個數(shù)據(jù)結(jié)構(gòu)對應(yīng)著自己的存儲介質(zhì)腊嗡。
?
?
由兩個樹狀結(jié)構(gòu)組成着倾,
C0:所有數(shù)據(jù)均存儲在內(nèi)存
C1:所有數(shù)據(jù)均存儲在磁盤之上
當(dāng)一條新的記錄插入的時候,先從C0中插入燕少,當(dāng)達(dá)到C0的閾值以后卡者,就將C0中的某些數(shù)據(jù)片段遷移到C1中并合并到C1樹上。當(dāng)C1層級達(dá)到閾值時客们,合并到C2層級崇决。由于合并排序算法是批量的、并且是順序存儲的镶摘,所以寫的速度十分快嗽桩。這樣層層合并岳守,文件數(shù)量越來越少凄敢,文件變得越來越大。每個層級的數(shù)據(jù)都是排序的湿痢,合并的時候通過類似歸并排序的算法實(shí)現(xiàn)快速排序涝缝。對于刪除操作,僅僅將數(shù)據(jù)標(biāo)記為已刪除譬重,合并的時候跳過已標(biāo)記為刪除的數(shù)據(jù)拒逮,達(dá)到物理刪除的效果。
LSM思想在HBase中的實(shí)現(xiàn)(三層存儲結(jié)構(gòu)):
?
?
Level 0:日志/內(nèi)存臀规,為了加速隨機(jī)寫的速度滩援,先寫入日志和內(nèi)存中,其中日志是為了保障高可用塔嬉。
Level 1:日志/內(nèi)存玩徊,當(dāng)達(dá)到閾值租悄,會有異步線程將部分?jǐn)?shù)據(jù)刷寫到硬盤上;恩袱;
Level 2:合并泣棋,由于不斷地刷寫會產(chǎn)生大量小文件,這樣不利于管理和查詢畔塔,需要在合適的時機(jī)啟動一個異步線程進(jìn)行合并操作會生成一個大文件(多路歸并算法)潭辈。
3.2 數(shù)據(jù)存儲模塊簡介
RegionServer = Region + Store + MemStore + StoreFile + HFile + HLog
?
?
Region :分布式存儲數(shù)據(jù)和負(fù)載均衡的最小單元,對于一個 RegionServer 可以包含很多Region澈吨,并且每一個Region 包含的數(shù)據(jù)都是互斥的把敢,存儲有用戶各個行的數(shù)據(jù)。
Store :對應(yīng)表中的列族谅辣。
MemStore :是一個內(nèi)存式的數(shù)據(jù)結(jié)構(gòu)技竟,用戶數(shù)據(jù)進(jìn)入Region 之后會先寫入MemStore當(dāng)滿了之后 再刷寫到StoreFile 中,在StoreFile 中將數(shù)據(jù)封裝成HFile再刷寫到HDFS上 屈藐。
HLog:對于一個RegionServer 只有一個HLog實(shí)例榔组。
HLog和MemStore 構(gòu)成了Level 0,保證了數(shù)據(jù)的高可用和性能的低延遲联逻。
StoreFile 和HFile 構(gòu)成了Level 1搓扯,實(shí)現(xiàn)了不可靠數(shù)據(jù)的持久化,真正地將HBase變成了高可用的數(shù)據(jù)庫系統(tǒng)包归。
3.3 Region 解析
每個一個Region 都會存儲在一個確定的Region Server上锨推,數(shù)據(jù)之間是互斥的關(guān)系。HBase表在行鍵上分割為多個Region公壤,它是HBae中分布式存儲和負(fù)載均衡的最小單元换可,但不是存儲的最小單元。Region 按照大小切分厦幅,每個表一行只有一個Region 沾鳄,一行數(shù)據(jù)不可能分布在多個Region 上。當(dāng)不斷插入導(dǎo)致列族到達(dá)閾值之后确憨,Region 會被水平拆分為兩個Region 译荞。Region 在Region Server的運(yùn)行過程中可能出現(xiàn)移動,這是Master的負(fù)載均衡策略或者因為出現(xiàn)宕機(jī)休弃。Region 是用戶和Region Server交互的實(shí)際載體吞歼,每個Region 都有三個信息來標(biāo)識:
Table Name(表名)
Start RowKey(起始的RowKey)
Create Time(創(chuàng)建時間)
?
?
Region 的拆分過程是:先該當(dāng)前Region 下線,然后對其進(jìn)行拆分塔猾,接著將子Region 加入到Meta的元信息中篙骡,再加入原Region Server上,最后同步到Master上。
3.4 HFile 解析
HBase實(shí)際以HFile的形式保存在HDFS上糯俗。
HFile文件是HBase存儲數(shù)據(jù)的最基礎(chǔ)形式慎皱,它的底層是Hadoop二進(jìn)制文件,是用戶數(shù)據(jù)的實(shí)際載體叶骨,存儲著K-V這樣的數(shù)據(jù)茫多。
?
?
Scanned block section:在順序掃描HFile的時候,這個部分的數(shù)據(jù)塊將會被讀取忽刽,用戶數(shù)據(jù)存儲于該部分天揖。
Nonscanned block section:在順序掃描HFile的時候,這個部分的數(shù)據(jù)塊將不會被讀取跪帝。主要包含一些元數(shù)據(jù)今膊,在訪問用戶數(shù)據(jù)的時候,該部分不會被掃描到伞剑。
Load-on-open section:當(dāng)RegionServer 啟動的時候斑唬,該部分?jǐn)?shù)據(jù)會被加載到內(nèi)存中,主要是HFile的一些元數(shù)據(jù)信息黎泣。
Trailer:記錄了HFile的基本信息恕刘,各個部分的偏移量和尋址信息。
?
?
Data Block:是HBase中最基礎(chǔ)的存儲單元抒倚,是實(shí)際存儲用戶的數(shù)據(jù)結(jié)構(gòu)褐着,存儲的是K-V數(shù)據(jù)。
KeyType的作用:對于HBase中的刪除操作托呕,由于HFile一旦刷寫成功就不可做修改含蓉,正常插入是Put,Delete表示刪除整行项郊,DeleteColumn表示刪除某一列馅扣,DeleteFamily表示刪除某個列族。這就是給數(shù)據(jù)打上一個標(biāo)記着降,稱為“墓碑標(biāo)記”差油,實(shí)際上標(biāo)識數(shù)據(jù)被刪除掉了。當(dāng)再次掃描的時候鹊碍,發(fā)現(xiàn)有“墓碑標(biāo)記”的時候厌殉,就會在以后的某個時間點(diǎn)將對應(yīng)的數(shù)據(jù)刪除,并不是在插入的過程中就將其進(jìn)行刪除侈咕,這也是為了刪除性能的高效性。
3.5 WAL 解析
HBase的日志系統(tǒng)器紧,WAL即預(yù)寫日志:
?
?
其最重要的功能就是災(zāi)難恢復(fù)耀销,解決了高可用,解決了遠(yuǎn)程備份。
WAL是通過HLog實(shí)例進(jìn)行實(shí)現(xiàn)的熊尉,HLog是使用append方法罐柳,對日志進(jìn)行追加寫的功能。WAL通過序列化的number去追蹤數(shù)據(jù)的改變狰住,其內(nèi)部實(shí)現(xiàn)使用了AtimoicLong來保證線程安全张吉。
?
?
- HLogKey:
?
?
HLogSyncer:日志同步刷寫類,有定時刷寫和內(nèi)存溢值兩種工作方式催植。
HLogRoller:Log的大小可以通過配置文件進(jìn)行設(shè)置肮蛹,默認(rèn)是一個小時,每經(jīng)過一個小時生成一個新的Log文件创南。當(dāng)一定時間后伦忠,就有大量的日志文件。HLogRoller是在特定的時間滾動日志生成新的日志文件稿辙,避免了單個日志文件過大昆码。根據(jù)序列化的number(Sequence Number)對比時間,刪除舊的不需要的日志文件邻储。
3.6 Compaction 解析
Compaction 會從Region Store中選擇一些HFile文件進(jìn)行合并赋咽,合并就是指將一些待合并的文件中的K-V對進(jìn)行排序重新生成一個新的文件取代原來的待合并的文件。由于系統(tǒng)不斷地進(jìn)行刷寫會產(chǎn)生大量小文件吨娜,這樣不利于數(shù)據(jù)查找冬耿。那么將這些小文件合并成一些大文件,這樣使得查找過程的I/O次數(shù)減少萌壳,提高了查找效率亦镶。其中可以分為以下兩類:
?
?
MinorCompaction:選取一些小的相鄰的Store File進(jìn)行合并一個更大的Store File,生成多個較大的Store File袱瓮。
MajorCompaction:將所有的Store File合并成一個Store File缤骨,這個過程中將清理被刪除的數(shù)據(jù)、TTL過期的數(shù)據(jù)尺借、版本號超過設(shè)定版本號的數(shù)據(jù)绊起。操作過程的時間比較長,消耗的資源也比較多燎斩。
HBase中Compaction的觸發(fā)時機(jī)的因素很多虱歪,最主要的有三種:
MemStore Flush :每次執(zhí)行完Flush 操作以后,都會進(jìn)行判斷當(dāng)超過閾值就會觸發(fā)一個合并栅表。
后臺線程周期性的檢查:Compaction Checker會定期觸發(fā)檢查是否需要合并笋鄙,這個線程會優(yōu)先檢查文件數(shù)是否大于閾值,一旦大于就會觸發(fā)合并怪瓶,若不滿足會繼續(xù)檢查是否滿足MajorCompaction萧落。簡單來說,就是如果當(dāng)前Store中最早更新時間早于某個值,這個值成為mc time找岖,就會觸發(fā)大的合并陨倡,HBase通過這種方式來刪除過期的數(shù)據(jù),其浮動區(qū)間為[7-7 * 0.2, 7+7 * 0.2]许布。默認(rèn)在七天會進(jìn)行一次大合并(MajorCompaction)兴革。
手動觸發(fā):通常是為了執(zhí)行MajorCompaction,因為很多業(yè)務(wù)擔(dān)心自動的MajorCompaction會影響性能蜜唾,會選擇在低峰期手動觸發(fā)杂曲;還可能用戶在進(jìn)行完alter操作以后,希望立即生效灵妨;管理員在發(fā)現(xiàn)硬盤容量不夠的時候會手動觸發(fā)解阅,這樣可以刪除大量的過期數(shù)據(jù)。
四泌霍、數(shù)據(jù)存取解析
4.1 數(shù)據(jù)存取流程解析
數(shù)據(jù)存儲(客戶端):
提交之前會先請求Zookeeper來確定Meta表(元數(shù)據(jù)表)所在的Region Server的地址货抄,再根據(jù)RowKey確定歸屬的Region Server,之后用戶提交Put/Delete這樣的請求朱转,HBase客戶端會將Put請求添加到本地的buffer中蟹地,符合一定的條件就會通過異步批量提交。
HBase默認(rèn)設(shè)置auto flush(自動刷寫)為true藤为,表示put請求會直接提交給服務(wù)器進(jìn)行處理怪与,用戶可以設(shè)置auto flush為false,這樣put請求會首先放入本地的buffer中缅疟,等到buffer的大小達(dá)到一定閾值(默認(rèn)是2M)后再提交分别。
?
?
數(shù)據(jù)存儲(服務(wù)器):
當(dāng)數(shù)據(jù)到達(dá)Region Server的某個Region后,首先獲取RowLock(行鎖)存淫,之后再寫入日志和緩存耘斩,持有行鎖的時候并不會同步日志,操作完釋放RowLock(行鎖)桅咆,隨后再將同步(sync)到HDFS上括授,如果同步失敗進(jìn)行回滾操作將緩存中已寫入的數(shù)據(jù)刪除掉,代表插入失敗岩饼。當(dāng)緩存達(dá)到一定閾值(默認(rèn)是64M)后荚虚,啟動異步線程將數(shù)據(jù)刷寫到硬盤上形成多個StoreFile,當(dāng)StoreFile數(shù)量達(dá)到一定閾值后會觸發(fā)合并操作籍茧。當(dāng)單個StoreFile的大小達(dá)到一定大小的時候會觸發(fā)一個split操作版述,將當(dāng)前的Region切分為兩個Region,再同步到Master上硕糊,原有Region會下線院水,子Region會被Master分配到相應(yīng)的Region Server上腊徙。
?
?
數(shù)據(jù)獲燃蚴(客戶端):
這里同數(shù)據(jù)存儲的過程是類似的檬某。
?
?
數(shù)據(jù)獲取(服務(wù)器):
Region Server在接收到客戶端的Get/Scan請求之后螟蝙,首先HBase在確定的Region Server上構(gòu)造一個RegionScanner準(zhǔn)備為當(dāng)前定位的Scan做檢索恢恼,RegionScanner會根據(jù)列族構(gòu)建StoreScanner,有多少個列族就會構(gòu)建多少個StoreScanner胰默。每個StoreScanner會為當(dāng)前Store中的每個HFile構(gòu)建一個StoreFileScanner场斑,用于實(shí)際執(zhí)行對應(yīng)的文件檢索。同時會對對應(yīng)的Mem構(gòu)建對應(yīng)的MemStoreScanner牵署,用于檢索MemStore中的數(shù)據(jù)漏隐。構(gòu)建兩類Scanner的原因在于,數(shù)據(jù)可能還沒有完全刷寫到硬盤上奴迅,部分?jǐn)?shù)據(jù)還存儲于內(nèi)存之中青责。檢索完之后,就能夠找到對應(yīng)的K-V取具,再經(jīng)過簡單地封裝就形成了ResultSet脖隶,就可以直接返回給客戶端。
?
?
4.2 數(shù)據(jù)存取優(yōu)化
存儲優(yōu)化:
HBase通過MemStore和WAL兩種機(jī)制暇检,實(shí)現(xiàn)數(shù)據(jù)順序快速的插入产阱,極大降低了數(shù)據(jù)存儲的延遲。
檢索(獲瓤槠汀)優(yōu)化:
HBase使用布隆過濾器來提高隨機(jī)讀的性能构蹬,布隆過濾器是列族級別的配置。HBase中的每個HFile都有對應(yīng)的位數(shù)組悔据,K-V在寫入HFile時庄敛,會經(jīng)過幾個哈希函數(shù)的映射并寫入對應(yīng)的位數(shù)組里面。HFile中的位數(shù)組蜜暑,就是布隆過濾器中存儲的值铐姚。HFile越大位數(shù)組也會越大,太大就不適合放入內(nèi)存中了肛捍,因此HFile將位數(shù)組以RowKey進(jìn)行了拆分隐绵,一部分連續(xù)的RowKey使用一個位數(shù)組。因此HFile會有多個位數(shù)組拙毫,在查詢的時候依许,首先會定位到某個位數(shù)組再將該位數(shù)組加載到內(nèi)存中進(jìn)行過濾就行,這樣減少了內(nèi)存的開支缀蹄。
HBase中存在兩種布隆過濾器:
Row:根據(jù)RowKey來過濾StoreFile峭跳,這種情況可以針對列族和列都相同膘婶,只有RowKey不同的情況;
RowCol:根據(jù)RowKey+ColumnQualifier(列描述符)來過濾StoreFile蛀醉,這種情況是針對列族相同悬襟,列和RowKey不同的情況。
五拯刁、特點(diǎn)
容量大:HBase單表可以有百億行脊岳、百萬列,數(shù)據(jù)矩陣橫向和縱向兩個緯度所支持的數(shù)據(jù)量級都非常具有彈性垛玻;
面向列:列是可以動態(tài)增加的割捅,不需要指定列,面向列的存儲和權(quán)限控制帚桩,并支持獨(dú)立檢索亿驾;
多版本:每一個列的數(shù)據(jù)存儲有個多Version;
稀疏性:為空的列不占用存儲空間账嚎;
擴(kuò)展性:底層依賴于HDFS莫瞬,空間不夠的時候只需要橫向擴(kuò)展即可;
高可靠性:副本機(jī)制保證了數(shù)據(jù)的可靠性醉锄;
高性能:寫入性能高乏悄,底層使用LSM數(shù)據(jù)結(jié)構(gòu)和RowKey有序排序等架構(gòu)上的獨(dú)特設(shè)計;讀性能高恳不,使用region切分檩小、主鍵索引和緩存機(jī)制使得具備隨機(jī)讀取性能高。
?
?
六烟勋、和關(guān)系型數(shù)據(jù)庫的對比
區(qū)別:
列動態(tài)增加规求;
數(shù)據(jù)自動切分;
高并發(fā)讀寫卵惦;
不支持條件查詢