一、背景
訂單本地化系統(tǒng)目前一個(gè)月的訂單的讀寫已經(jīng)切至jimkv存儲(chǔ),對(duì)應(yīng)的HBase集群已下線。但存儲(chǔ)全量數(shù)據(jù)的HBase集群仍在使用,計(jì)劃將這個(gè)HBase集群中的數(shù)據(jù)全部遷到j(luò)imkv,徹底下線這個(gè)HBase集群。由于這個(gè)集群目前仍在線上讀寫,本文從原理和實(shí)踐的角度探索對(duì)HBase集群數(shù)據(jù)的在線遷移的方案,歡迎大家補(bǔ)充。
二、基礎(chǔ)理論梳理
HBase整體架構(gòu)
重溫一下各個(gè)模塊的職責(zé)
HBase客戶端
HBase客戶端(Client)提供了Shell命令行接口、原生Java API編程接口、Thrift/REST API編程接口以及MapReduce編程接口。HBase客戶端支持所有常見的DML操作以及DDL操作,即數(shù)據(jù)的增刪改查和表的日常維護(hù)等。其中Thrift/REST API主要用于支持非Java的上層業(yè)務(wù)需求,MapReduce接口主要用于批量數(shù)據(jù)導(dǎo)入以及批量數(shù)據(jù)讀取。HBase客戶端訪問數(shù)據(jù)行之前,首先需要通過元數(shù)據(jù)表定位目標(biāo)數(shù)據(jù)所在RegionServer,之后才會(huì)發(fā)送請(qǐng)求到該RegionServer。同時(shí)這些元數(shù)據(jù)會(huì)被緩存在客戶端本地,以方便之后的請(qǐng)求訪問。如果集群RegionServer發(fā)生宕機(jī)或者執(zhí)行了負(fù)載均衡等,從而導(dǎo)致數(shù)據(jù)分片發(fā)生遷移,客戶端需要重新請(qǐng)求最新的元數(shù)據(jù)并緩存在本地。
Master
Master主要負(fù)責(zé)HBase系統(tǒng)的各種管理工作:
?處理用戶的各種管理請(qǐng)求,包括建表、修改表、權(quán)限操作、切分表、合并數(shù)據(jù)分片以及Compaction等。
?管理集群中所有RegionServer,包括RegionServer中Region的負(fù)載均衡、RegionServer的宕機(jī)恢復(fù)以及Region的遷移等。
?清理過期日志以及文件,Master會(huì)每隔一段時(shí)間檢查HDFS中HLog是否過期、HFile是否已經(jīng)被刪除,并在過期之后將其刪除。
RegionServer
RegionServer主要用來響應(yīng)用戶的IO請(qǐng)求,是HBase中最核心的模塊,由WAL(HLog)、BlockCache以及多個(gè)Region構(gòu)成。
?WAL(HLog):HLog在HBase中有兩個(gè)核心作用——其一,用于實(shí)現(xiàn)數(shù)據(jù)的高可靠性,HBase數(shù)據(jù)隨機(jī)寫入時(shí),并非直接寫入HFile數(shù)據(jù)文件,而是先寫入緩存,再異步刷新落盤。為了防止緩存數(shù)據(jù)丟失,數(shù)據(jù)寫入緩存之前需要首先順序?qū)懭際Log,這樣,即使緩存數(shù)據(jù)丟失,仍然可以通過HLog日志恢復(fù);其二,用于實(shí)現(xiàn)HBase集群間主從復(fù)制,通過回放主集群推送過來的HLog日志實(shí)現(xiàn)主從復(fù)制。
?BlockCache:HBase系統(tǒng)中的讀緩存??蛻舳藦拇疟P讀取數(shù)據(jù)之后通常會(huì)將數(shù)據(jù)緩存到系統(tǒng)內(nèi)存中,后續(xù)訪問同一行數(shù)據(jù)可以直接從內(nèi)存中獲取而不需要訪問磁盤。對(duì)于帶有大量熱點(diǎn)讀的業(yè)務(wù)請(qǐng)求來說,緩存機(jī)制會(huì)帶來極大的性能提升。
對(duì)于帶有大量熱點(diǎn)讀的業(yè)務(wù)請(qǐng)求來說,緩存機(jī)制會(huì)帶來極大的性能提升。BlockCache緩存對(duì)象是一系列Block塊,一個(gè)Block默認(rèn)為64K,由物理上相鄰的多個(gè)KV數(shù)據(jù)組成。BlockCache同時(shí)利用了空間局部性和時(shí)間局部性原理,前者表示最近將讀取的KV數(shù)據(jù)很可能與當(dāng)前讀取到的KV數(shù)據(jù)在地址上是鄰近的,緩存單位是Block(塊)而不是單個(gè)KV就可以實(shí)現(xiàn)空間局部性;后者表示一個(gè)KV數(shù)據(jù)正在被訪問,那么近期它還可能再次被訪問。當(dāng)前BlockCache主要有兩種實(shí)現(xiàn)——LRUBlockCache和BucketCache,前者實(shí)現(xiàn)相對(duì)簡(jiǎn)單,而后者在GC優(yōu)化方面有明顯的提升。
?Region:數(shù)據(jù)表的一個(gè)分片,當(dāng)數(shù)據(jù)表大小超過一定閾值就會(huì)“水平切分”,分裂為兩個(gè)Region。Region是集群負(fù)載均衡的基本單位。通常一張表的Region會(huì)分布在整個(gè)集群的多臺(tái)RegionServer上,一個(gè)RegionServer上會(huì)管理多個(gè)Region,當(dāng)然,這些Region一般來自不同的數(shù)據(jù)表。
一個(gè)Region由一個(gè)或者多個(gè)Store構(gòu)成,Store的個(gè)數(shù)取決于表中列簇(column family)的個(gè)數(shù),多少個(gè)列簇就有多少個(gè)Store。HBase中,每個(gè)列簇的數(shù)據(jù)都集中存放在一起形成一個(gè)存儲(chǔ)單元Store,因此建議將具有相同IO特性的數(shù)據(jù)設(shè)置在同一個(gè)列簇中。每個(gè)Store由一個(gè)MemStore和一個(gè)或多個(gè)HFile組成。MemStore稱為寫緩存,用戶寫入數(shù)據(jù)時(shí)首先會(huì)寫到MemStore,當(dāng)MemStore寫滿之后(緩存數(shù)據(jù)超過閾值,默認(rèn)128M)系統(tǒng)會(huì)異步地將數(shù)據(jù)f lush成一個(gè)HFile文件。顯然,隨著數(shù)據(jù)不斷寫入,HFile文件會(huì)越來越多,當(dāng)HFile文件數(shù)超過一定閾值之后系統(tǒng)將會(huì)執(zhí)行Compact操作,將這些小文件通過一定策略合并成一個(gè)或多個(gè)大文件。
HDFS
HBase底層依賴HDFS組件存儲(chǔ)實(shí)際數(shù)據(jù),包括用戶數(shù)據(jù)文件、HLog日志文件等最終都會(huì)寫入HDFS落盤。HDFS是Hadoop生態(tài)圈內(nèi)最成熟的組件之一,數(shù)據(jù)默認(rèn)三副本存儲(chǔ)策略可以有效保證數(shù)據(jù)的高可靠性。HBase內(nèi)部封裝了一個(gè)名為DFSClient的HDFS客戶端組件,負(fù)責(zé)對(duì)HDFS的實(shí)際數(shù)據(jù)進(jìn)行讀寫訪問。
三、數(shù)據(jù)遷移方案調(diào)研
1、如何定位一條數(shù)據(jù)在哪個(gè)region
HBase一張表的數(shù)據(jù)是由多個(gè)Region構(gòu)成,而這些Region是分布在整個(gè)集群的RegionServer上的。那么客戶端在做任何數(shù)據(jù)操作時(shí),都要先確定數(shù)據(jù)在哪個(gè)Region上,然后再根據(jù)Region的RegionServer信息,去對(duì)應(yīng)的RegionServer上讀取數(shù)據(jù)。因此,HBase系統(tǒng)內(nèi)部設(shè)計(jì)了一張?zhí)厥獾谋怼猦base:meta表,專門用來存放整個(gè)集群所有的Region信息。
hbase:meta表的結(jié)構(gòu)如下,整個(gè)表只有一個(gè)名為info的列族。而且HBase保證hbase:meta表始終只有一個(gè)Region,這是為了確保meta表多次操作的原子性。
hbase:meta的一個(gè)rowkey就對(duì)應(yīng)一個(gè)Region,rowkey主要由TableName(業(yè)務(wù)表名)、StartRow(業(yè)務(wù)表Region區(qū)間的起始rowkey)、Timestamp(Region創(chuàng)建的時(shí)間戳)、EncodedName(上面3個(gè)字段的MD5 Hex值)4個(gè)字段拼接而成。每一行數(shù)據(jù)又分為4列,分別是info:regioninfo、info:seqnumDuringOpen、info:server、info:serverstartcode。
?info:regioninfo:該列對(duì)應(yīng)的Value主要存儲(chǔ)4個(gè)信息,即EncodedName、RegionName、Region的StartRow、Region的StopRow。
?info:seqnumDuringOpen:該列對(duì)應(yīng)的Value主要存儲(chǔ)Region打開時(shí)的sequenceId。
?info:server:該列對(duì)應(yīng)的Value主要存儲(chǔ)Region落在哪個(gè)RegionServer上。
?info:serverstartcode:該列對(duì)應(yīng)的Value主要存儲(chǔ)所在RegionServer的啟動(dòng)Timestamp。
為了解決如果所有的流量都先請(qǐng)求hbase:meta表找到Region,再請(qǐng)求Region所在的RegionServer,那么hbase:meta表的將承載巨大的壓力,這個(gè)Region將馬上成為熱點(diǎn)Region這個(gè)問題,HBase會(huì)把hbase:meta表的Region信息緩存在HBase客戶端。在HBase客戶端有一個(gè)叫做MetaCache的緩存,在調(diào)用HBase API時(shí),客戶端會(huì)先去MetaCache中找到業(yè)務(wù)rowkey所在的Region。
2、HBase client Scan用法
HBase客戶端提供了一系列可以批量掃描數(shù)據(jù)的api,主要有ScanAPI、TableScanMR、SnapshotScanM
HBase client scan demo
public class TestDemo {
private static final HBaseTestingUtility TEST_UTIL=new HBaseTestingUtility();
public static final TableName tableName=TableName.valueOf("testTable");
public static final byte[] ROW_KEY0=Bytes.toBytes("rowkey0");
public static final byte[] ROW_KEY1=Bytes.toBytes("rowkey1");
public static final byte[] FAMILY=Bytes.toBytes("family");
public static final byte[] QUALIFIER=Bytes.toBytes("qualifier");
public static final byte[] VALUE=Bytes.toBytes("value");
@BeforeClass
public static void setUpBeforeClass() throws Exception {
TEST_UTIL.startMiniCluster();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}
@Test
public void test() throws IOException {
Configuration conf=TEST_UTIL.getConfiguration();
try (Connection conn=ConnectionFactory.createConnection(conf)) {
try (Table table=conn.getTable(tableName)) {
for (byte[] rowkey : new byte[][] { ROW_KEY0, ROW_KEY1 }) {
Put put=new Put(rowkey).addColumn(FAMILY, QUALIFIER, VALUE);
table.put(put);
}
Scan scan=new Scan().withStartRow(ROW_KEY1).setLimit(1);
try (ResultScanner scanner=table.getScanner(scan)) {
List< Cell > cells=new ArrayList< >();
for (Result result : scanner) {
cells.addAll(result.listCells());
}
Assert.assertEquals(cells.size(), 1);
Cell firstCell=cells.get(0);
Assert.assertArrayEquals(CellUtil.cloneRow(firstCell), ROW_KEY1);
Assert.assertArrayEquals(CellUtil.cloneFamily(firstCell), FAMILY);
Assert.assertArrayEquals(CellUtil.cloneQualifier(firstCell), QUALIFIER);
Assert.assertArrayEquals(CellUtil.cloneValue(firstCell), VALUE);
}
}
}
}
}
Scan API
使用ScanAPI獲取Result的流程如下,在上面的demo代碼中,table.getScanner(scan)可以拿到一個(gè)scanner,然后只要不斷地執(zhí)行scanner.next()就能拿到一個(gè)Result,客戶端Scan的核心流程如下
用戶每次執(zhí)行scanner.next(),都會(huì)嘗試去名為cache的隊(duì)列中拿result(步驟4)。如果cache隊(duì)列已經(jīng)為空,則會(huì)發(fā)起一次RPC向服務(wù)端請(qǐng)求當(dāng)前scanner的后續(xù)result數(shù)據(jù)(步驟1)??蛻舳耸盏絩esult列表之后(步驟2),通過scanResultCache把這些results內(nèi)的多個(gè)cell進(jìn)行重組,最終組成用戶需要的result放入到Cache中(步驟3)。其中,步驟1+步驟2+步驟3統(tǒng)稱為loadCache操作。為什么需要在步驟3對(duì)RPC response中的result進(jìn)行重組呢?這是因?yàn)镽egionServer為了避免被當(dāng)前RPC請(qǐng)求耗盡資源,實(shí)現(xiàn)了多個(gè)維度的資源限制(例如timeout、單次RPC響應(yīng)最大字節(jié)數(shù)等),一旦某個(gè)維度資源達(dá)到閾值,就馬上把當(dāng)前拿到的cell返回給客戶端。這樣客戶端拿到的result可能就不是一行完整的數(shù)據(jù),因此在步驟3需要對(duì)result進(jìn)行重組。
梳理完scanner的執(zhí)行流程之后,再看下Scan的幾個(gè)重要的概念。
?caching:每次loadCache操作最多放caching個(gè)result到cache隊(duì)列中??刂芻aching,也就能控制每次loadCache向服務(wù)端請(qǐng)求的數(shù)據(jù)量,避免出現(xiàn)某一次scanner.next()操作耗時(shí)極長(zhǎng)的情況。
?batch:用戶拿到的result中最多含有一行數(shù)據(jù)中的batch個(gè)cell。如果某一行有5個(gè)cell,Scan設(shè)的batch為2,那么用戶會(huì)拿到3個(gè)result,每個(gè)result中cell個(gè)數(shù)依次為2,2,1。
?allowPartial:用戶能容忍拿到一行部分cell的result。設(shè)置了這個(gè)屬性,將跳過圖4-3中的第三步重組流程,直接把服務(wù)端收到的result返回給用戶。
?maxResultSize:loadCache時(shí)單次RPC操作最多拿到maxResultSize字節(jié)的結(jié)果集。
缺點(diǎn):不能并發(fā)執(zhí)行,如果掃描的數(shù)據(jù)分布在不同的region上面,scan不會(huì)并發(fā)執(zhí)行,而是一行一行的去掃,且在步驟1和步驟2期間,client端一致在阻塞等待,所以從客戶端視角來看整個(gè)掃描時(shí)間=客戶端處理數(shù)據(jù)時(shí)間+服務(wù)器端掃描數(shù)據(jù)時(shí)間。
應(yīng)用場(chǎng)景:根據(jù)上面的分析,scan API的效率很大程度上取決于掃描的數(shù)據(jù)量。通常建議OLTP業(yè)務(wù)中少量數(shù)據(jù)量掃描的scan可以使用scan API,大量數(shù)據(jù)的掃描使用scan API,掃描性能有時(shí)候并不能夠得到有效保證。
最佳實(shí)踐:
1.批量OLAP掃描業(yè)務(wù)建議不要使用ScanAPI,ScanAPI適用于少量數(shù)據(jù)掃描場(chǎng)景(OLTP場(chǎng)景)
2.建議所有scan盡可能都設(shè)置startkey以及stopkey減少掃描范圍
3.建議所有僅需要掃描部分列的scan盡可能通過接口setFamilyMap設(shè)置列族以及列
TableScanMR
對(duì)于掃描大量數(shù)據(jù)的這類業(yè)務(wù),HBase目前提供了兩種基于MR掃描的用法,分別為TableScanMR以及SnapshotScanMR。首先來介紹TableScanMR,具體用法參考官方文檔https://hbase.apache.org/book.html#mapreduce.example.read,TableScanMR的工作原理說白了就是ScanAPI的并行化。如下圖所示:
TableScanMR會(huì)將scan請(qǐng)求根據(jù)目標(biāo)region的分界進(jìn)行分解,分解成多個(gè)sub-scan,每個(gè)sub-scan本質(zhì)上就是一個(gè)ScanAPI。假如scan是全表掃描,那這張表有多少region,就會(huì)將這個(gè)scan分解成多個(gè)sub-scan,每個(gè)sub-scan的startkey和stopkey就是region的startkey和stopkey。
最佳實(shí)踐:
1.TableScanMR設(shè)計(jì)為OLAP場(chǎng)景使用,因此在離線掃描時(shí)盡可能使用該種方式
2.TableScanMR原理上主要實(shí)現(xiàn)了ScanAPI的并行化,將scan按照region邊界進(jìn)行切分。這種場(chǎng)景下整個(gè)scan的時(shí)間基本等于最大region掃描的時(shí)間。在某些有數(shù)據(jù)傾斜的場(chǎng)景下可能出現(xiàn)某一個(gè)region上有大量待掃描數(shù)據(jù),而其他大量region上都僅有很少的待掃描數(shù)據(jù)。這樣并行化效果并不好。針對(duì)這種數(shù)據(jù)傾斜的場(chǎng)景TableScanMR做了平衡處理,它會(huì)將大region上的scan切分成多個(gè)小的scan使得所有分解后的scan掃描的數(shù)據(jù)量基本相當(dāng)。這個(gè)優(yōu)化默認(rèn)是關(guān)閉的,需要設(shè)置參數(shù)”hbase.mapreduce.input.autobalance”為true。因此建議大家使用TableScanMR時(shí)將該參數(shù)設(shè)置為true。
3.盡量將掃描表中相鄰的小region合并成大region,而將大region切分成稍微小點(diǎn)的region
SnapshotScanMR
SnapshotScanMR與TableScanMR相同都是使用MR并行化對(duì)數(shù)據(jù)進(jìn)行掃描,兩者用法也基本相同,直接使用TableScanMR的用法,在此基礎(chǔ)上做部分修改即可,它們最大的區(qū)別主要有兩點(diǎn):
1.SnapshotScanMR掃描于原始表對(duì)應(yīng)的snapshot之上(更準(zhǔn)確來說根據(jù)snapshot restore出來的hfile),而TableScanMR掃描于原始表。
2.SnapshotScanMR直接會(huì)在客戶端打開region掃描HDFS上的文件,不需要發(fā)送Scan請(qǐng)求給RegionServer,再有RegionServer掃描HDFS上的文件。在客戶端直接掃描HDFS上的文件,這類scanner稱之為ClientSideRegionScanner。
總體來看和TableScanMR工作流程基本一致,最大的不同來自region掃描HDFS這個(gè)模塊,TableScanMR中這個(gè)模塊來自于regionserver,而SnapshotScanMR中客戶端直接繞過regionserver在客戶端借用region中的掃描機(jī)制直接掃描hdfs中數(shù)據(jù)。這樣做的優(yōu)點(diǎn)如下:
1.減小對(duì)RegionServer的影響。很顯然,SnapshotScanMR這種繞過RegionServer的實(shí)現(xiàn)方式最大限度的減小了對(duì)集群中其他業(yè)務(wù)的影響。
2.極大的提升了掃描效率。SnapshotScanMR相比TableScanMR在掃描效率上會(huì)有2倍~N倍的性能提升(下一小節(jié)對(duì)各種掃描用法性能做個(gè)對(duì)比評(píng)估)。主要原因如下:掃描的過程少了一次網(wǎng)絡(luò)傳輸,對(duì)于大數(shù)據(jù)量的掃描,網(wǎng)絡(luò)傳輸花費(fèi)的時(shí)間是非常龐大的,這主要可能牽扯到數(shù)據(jù)的序列化以及反序列化開銷。TableScanMR掃描中RegionServer很可能會(huì)成為瓶頸,而SnapshotScanMR掃描并沒有這個(gè)瓶頸點(diǎn)。
性能對(duì)比(來自網(wǎng)圖)
3、業(yè)界常用的數(shù)據(jù)遷移方案
Hadoop層數(shù)據(jù)遷移
Hadoop層的數(shù)據(jù)遷移主要用到DistCp(Distributed Copy), HBase的所有文件都存儲(chǔ)在HDFS上,因此只要使用Hadoop提供的文件復(fù)制工具distcp將HBASE目錄復(fù)制到同一HDFS或者其他HDFS的另一個(gè)目錄中,就可以完成對(duì)源HBase集群的備份工作。
缺點(diǎn):源集群需要停寫,不可行。
HBase層數(shù)據(jù)遷移
- copyTable
copyTable也是屬于HBase層的數(shù)據(jù)遷移工具之一,從0.94版本開始支持,以表級(jí)別進(jìn)行數(shù)據(jù)遷移。通過MapReduce程序全表掃描待備份表數(shù)據(jù)并寫入另一個(gè)集群,與DistCp不同的時(shí),它是利用MR去scan 原表的數(shù)據(jù),然后把scan出來的數(shù)據(jù)寫入到目標(biāo)集群的表。
缺點(diǎn):全表臊面+數(shù)據(jù)深拷貝,對(duì)源表的讀寫性能有很大影響,效率低。需要在使用過程中限定掃描原表的速度和傳輸?shù)膸挘襝opyTable不保證數(shù)據(jù)一致性,在大型集群遷移上這個(gè)工具使用比較少,很難控制。
- Export/Import
此方式與CopyTable類似,主要是將HBase表數(shù)據(jù)轉(zhuǎn)換成Sequence File并dump到HDFS,也涉及Scan表數(shù)據(jù),與CopyTable相比,還多支持不同版本數(shù)據(jù)的拷貝,同時(shí)它拷貝時(shí)不是將HBase數(shù)據(jù)直接Put到目標(biāo)集群表,而是先轉(zhuǎn)換成文件,把文件同步到目標(biāo)集群后再通過Import到線上表。
- Snapshot
Snapshot備份以快照技術(shù)為基礎(chǔ)原理,備份過程不需要拷貝任何數(shù)據(jù),因此對(duì)當(dāng)前集群幾乎沒有任何影響,備份速度非??於铱梢员WC數(shù)據(jù)一致性。筆者推薦在0.98之后的版本都使用Snapshot工具來完成在線備份任務(wù)。 參考: https://hbase.apache.org/book.html#ops.backup
4、Snapshot功能
常用場(chǎng)景
HBase在0.98版本推出在線Snapshot備份功能,使用在線snapshot備份功能常用于如下兩種情況:
?全量/增量備份。
○使用場(chǎng)景一:通常情況下,對(duì)于重要的業(yè)務(wù)數(shù)據(jù),建議每天執(zhí)行一次Snapshot來保存數(shù)據(jù)的快照記錄,并且定期清理過期快照,這樣如果業(yè)務(wù)發(fā)生嚴(yán)重錯(cuò)誤,可以回滾到之前的一個(gè)快照點(diǎn)。
○使用場(chǎng)景二:如果要對(duì)集群做重大升級(jí),建議升級(jí)前對(duì)重要的表執(zhí)行一次Snapshot,一旦升級(jí)有任何異常可以快速回滾到升級(jí)前。
?數(shù)據(jù)遷移
可以使用ExportSnapshot功能將快照導(dǎo)出到另一個(gè)集群,實(shí)現(xiàn)數(shù)據(jù)的遷移。
○使用場(chǎng)景一:機(jī)房在線遷移。比如業(yè)務(wù)集群在A機(jī)房,因?yàn)锳機(jī)房機(jī)位不夠或者機(jī)架不夠需要將整個(gè)集群遷移到另一個(gè)容量更大的B集群,而且在遷移過程中不能停服。基本遷移思路是,先使用Snapshot在B集群恢復(fù)出一個(gè)全量數(shù)據(jù),再使用replication技術(shù)增量復(fù)制A集群的更新數(shù)據(jù),等待兩個(gè)集群數(shù)據(jù)一致之后將客戶端請(qǐng)求重定向到B機(jī)房。
○使用場(chǎng)景二:利用Snapshot將表數(shù)據(jù)導(dǎo)出到HDFS,再使用HiveSpark等進(jìn)行離線OLAP分析,比如審計(jì)報(bào)表、月度報(bào)表等。
基本原理
Snapshot機(jī)制并不會(huì)拷貝數(shù)據(jù),可以理解為它是原數(shù)據(jù)的一份指針。在HBase的LSM樹類型系統(tǒng)結(jié)構(gòu)下是比較容易理解的,我們知道HBase數(shù)據(jù)文件一旦落到磁盤就不再允許更新刪除等原地修改操作,如果想更新刪除只能追加寫入新文件。這種機(jī)制下實(shí)現(xiàn)某個(gè)表的Snapshot,只需為當(dāng)前表的所有文件分別新建一個(gè)引用(指針)。對(duì)于其他新寫入的數(shù)據(jù),重新創(chuàng)建一個(gè)新文件寫入即可。如下圖所示
實(shí)踐過程
我在阿里云上搭建了一個(gè)輕量級(jí)的haddop和HBase集群,使用Snapshot功能步驟如下:
- 在目標(biāo)集群上建立表結(jié)構(gòu)一樣的表。
$ hbase shell
hbase > create 'myTable', 'cf1', 'cf2'
- 在原集群上對(duì)表初始化數(shù)據(jù)。
$ hbase shell
hbase > put 'myTable', 'row1', 'cf1:a', 'value1'
hbase > put 'myTable', 'row2', 'cf2:b', 'value2'
hbase > scan 'myTable'
ROW COLUMN+CELL row1 column=cf1:a, timestamp=2023-08-09T16:43:10.024, value=value1 row2 column=cf2:b, timestamp=2023-08-09T16:43:20.036, value=value2
- 使用 hbase shell 在原始集群中創(chuàng)建一個(gè)快照。
$ hbase shell
hbase >snapshot 'myTable', 'myTableSnapshot'
這里 'myTable' 是 hbase 的表名,'myTableSnapshot' 是快照的名稱。創(chuàng)建完成后可使用 list_snapshots 確認(rèn)是否成功,或使用 delete_snapshot 刪除快照。
hbase > delete_snapshot 'myTableSnapshot'
- 在源集群中導(dǎo)出快照到目標(biāo)集群。
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot myTableSnapshot -copy-to hdfs://10.0.0.38:4007/hbase/snapshot/myTableSnapshot
這里 10.0.0.38:4007 是目標(biāo)集群的 **activeip:**rpcport,導(dǎo)出快照時(shí)系統(tǒng)級(jí)別會(huì)啟動(dòng)一個(gè) mapreduce 的任務(wù),可以在后面增加 -mappers 16 -bandwidth 200 來指定 mapper 和帶寬。其中200指的是200MB/sec。
- 快照還原到目標(biāo)集群的目標(biāo) HDFS,在目標(biāo)集群中執(zhí)行如下命令。
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot myTableSnapshot -copy-from /hbase/snapshot/myTableSnapshot -copy-to /hbase/
- 在目標(biāo)集群從 hdfs 恢復(fù)相應(yīng)的 hbase 表及數(shù)據(jù)。
hbase > disable "myTable"
hbase > restore_snapshot 'myTableSnapshot'
hbase > enable 'myTable'
- 對(duì)于新表進(jìn)行測(cè)試
注意事項(xiàng)
訂單本地化HDD目前order_info_2023這張表分布在1500多個(gè)不同的region上,按照各種參考資料的理論來說,使用snapshot易超時(shí),該如何解決這個(gè)問題?有沒有什么方法能使做Snapshot更高效?網(wǎng)上關(guān)于這部分的資料太少,目前找不到太深入全面的解析。還有測(cè)試環(huán)境如何走這個(gè)流程?
使用snapshot注意需要申請(qǐng)zk、hbase-master節(jié)點(diǎn)的shell的管理員權(quán)限。
5、讀數(shù)據(jù)時(shí)的注意事項(xiàng)
關(guān)于scan時(shí)緩存的設(shè)置
原理:HBase業(yè)務(wù)通常一次scan就會(huì)返回大量數(shù)據(jù),因此客戶端發(fā)起一次scan請(qǐng)求,實(shí)際并不會(huì)一次就將所有數(shù)據(jù)加載到本地,而是分成多次RPC請(qǐng)求進(jìn)行加載,這樣設(shè)計(jì)一方面因?yàn)榇罅繑?shù)據(jù)請(qǐng)求可能會(huì)導(dǎo)致網(wǎng)絡(luò)帶寬嚴(yán)重消耗進(jìn)而影響其他業(yè)務(wù),另一方面因?yàn)閿?shù)據(jù)量太大可能導(dǎo)致本地客戶端發(fā)生OOM。在這樣的設(shè)計(jì)體系下,用戶會(huì)首先加載一部分?jǐn)?shù)據(jù)到本地,然后遍歷處理,再加載下一部分?jǐn)?shù)據(jù)到本地處理,如此往復(fù),直至所有數(shù)據(jù)都加載完成。數(shù)據(jù)加載到本地就存放在scan緩存中,默認(rèn)為100條數(shù)據(jù)。通常情況下,默認(rèn)的scan緩存設(shè)置是可以正常工作的。但是對(duì)于一些大scan(一次scan可能需要查詢幾萬甚至幾十萬行數(shù)據(jù)),每次請(qǐng)求100條數(shù)據(jù)意味著一次scan需要幾百甚至幾千次RPC請(qǐng)求,這種交互的代價(jià)是很大的。因此可以考慮將scan緩存設(shè)置增大,比如設(shè)為500或者1000條可能更加合適?!禜Base原理與實(shí)踐》作者提到,之前做過一次試驗(yàn),在一次scan 10w+條數(shù)據(jù)量的條件下,將scan緩存從100增加到1000條,可以有效降低scan請(qǐng)求的總體延遲,延遲降低了25%左右。
建議:大scan場(chǎng)景下將scan緩存從100增大到500或者1000,用以減少RPC次數(shù)。
關(guān)于離線批量讀時(shí)緩存的設(shè)置
原理:通常在離線批量讀取數(shù)據(jù)時(shí)會(huì)進(jìn)行一次性全表掃描,一方面數(shù)據(jù)量很大,另一方面請(qǐng)求只會(huì)執(zhí)行一次。這種場(chǎng)景下如果使用scan默認(rèn)設(shè)置,就會(huì)將數(shù)據(jù)從HDFS加載出來放到緩存??上攵?,大量數(shù)據(jù)進(jìn)入緩存必將其他實(shí)時(shí)業(yè)務(wù)熱點(diǎn)數(shù)據(jù)擠出,其他業(yè)務(wù)不得不從HDFS加載,進(jìn)而造成明顯的讀延遲毛刺。
建議:離線批量讀取請(qǐng)求設(shè)置禁用緩存,scan.setCacheBlocks (false)。
四、方案設(shè)計(jì)
五、代碼實(shí)現(xiàn)
對(duì)于HBase各種常用的DDL、DML操作的api匯總到這里
http://xingyun.jd.com/codingRoot/yanghelin3/hbase-api/
使用mapreduce方式遷移實(shí)現(xiàn)匯總到這里
http://xingyun.jd.com/codingRoot/yanghelin3/hbase-mapreduce/
REFERENCE
參考資料
HBase官方文檔:[http://hbase.apache.org/book.html#arch.overview]
HBase官方博客:[https://blogs.apache.org/hbase]
cloudera官方HBase博客:[https://blog.cloudera.com/blog/category/hbase]
HBasecon官網(wǎng):[http://hbase.apache.org/www.hbasecon.com]
HBase開發(fā)社區(qū):[https://issues.apache.org/jira/pr
HBase中文社區(qū):[http://hbase.group]
《Hbase原理與實(shí)踐 》
snapshot功能介紹
[https://blog.cloudera.com/introduction-to-apache-hbase-snapshots/]
[https://blog.cloudera.com/introduction-to-apache-hbase-snapshots-part-2-deeper-dive/]
[https://hbase.apache.org/book.html#ops.backup]
如何使用snapshot進(jìn)行復(fù)制
[https://docs.cloudera.com/documentation/enterprise/5-5-x/topics/cdh_bdr_hbase_replication.html#topic_20_11_7]
審核編輯 黃宇
-
接口
+關(guān)注
關(guān)注
33文章
8963瀏覽量
153335 -
編程
+關(guān)注
關(guān)注
88文章
3686瀏覽量
94951 -
數(shù)據(jù)遷移
+關(guān)注
關(guān)注
0文章
81瀏覽量
7083 -
HDFS
+關(guān)注
關(guān)注
1文章
31瀏覽量
9840 -
Hbase
+關(guān)注
關(guān)注
0文章
27瀏覽量
11393
發(fā)布評(píng)論請(qǐng)先 登錄
再談全局網(wǎng)HBase八大應(yīng)用場(chǎng)景
HBase性能優(yōu)化方法總結(jié)
阿里HBase的數(shù)據(jù)管道設(shè)施實(shí)踐與演進(jìn)
大數(shù)據(jù)時(shí)代數(shù)據(jù)庫-云HBase架構(gòu)&生態(tài)&實(shí)踐
企業(yè)打開云HBase的正確方式,來自阿里云云數(shù)據(jù)庫團(tuán)隊(duì)的解讀
HBase read replicas 功能介紹系列
大數(shù)據(jù)學(xué)習(xí)之Hbase shell的基本操作
兌吧:從自建HBase遷移到阿里云HBase實(shí)戰(zhàn)經(jīng)驗(yàn)
hbase工作原理_hbase超詳細(xì)介紹

hbase性能測(cè)試總結(jié)

評(píng)論