从mysql向HBase+Phoenix迁移数据的心得总结
* 轉(zhuǎn)載請(qǐng)注明出處 - yosql473 - 格物致知,經(jīng)世致用
mysql -> HBase + Phoenix
1.總體方案有哪些?
1)通過(guò)Sqoop直接從服務(wù)器(JDBC方式)抽取數(shù)據(jù)到HBase中
因?yàn)閿?shù)據(jù)量非常大,因此優(yōu)先考慮用Sqoop和MR抽取。
使用Sqoop抽取數(shù)據(jù)有一個(gè)問(wèn)題,就是Phoenix插入的數(shù)據(jù)和HBase插入的數(shù)據(jù)是不同的:
例如,使用Phoenix插入這么一條數(shù)據(jù):
upsert into tb_collector_log_143 values ( '2018-07-02 18:34:52_c37b03789c5e43ddb800ff90c27e5a44','2182a29047f3435885fc3fb9f7212189','server','server','2018-07-02 18:34:52','2018-07-02 18:34:52','8a5381604b4443ecb1b73d362f756483','c37b03789c5e43ddb800ff90c27e5a44','0560337357604a258a19adb8cc8849c6','2018-07-02 18:34:52','1','02','117.61.15.14:45067','4da7408331794910aa3523b6a9741df5');
在HBase中“2018-07-02 18:34:52”這個(gè)字段值(在phoenix中是date類(lèi)型)就是字節(jié)碼“\x80\x00\x01d\x5CF\xA8\xE0“:
2018-07-02 18:34:52_c37b03789c5e43ddb800ff90c27e5a44 column=0:OPERATER_DATE, timestamp=1541250071138, value=\x80\x00\x01d\x5CF\xA8\xE0
因此如果直接向HBase put數(shù)據(jù),也會(huì)出現(xiàn)Phoenix無(wú)法識(shí)別的問(wèn)題。經(jīng)過(guò)反復(fù)的驗(yàn)證,發(fā)現(xiàn)只有Phoenix的字符串類(lèi)型(varchar和char)才能保持HBase中直接存儲(chǔ)這個(gè)值。
* 因此,為了讓在Phoenix中插入字符串“aaa"與在HBase中插入”aaa"等價(jià),被插入的這個(gè)字段只能是char或者是varchar類(lèi)型。 這也就意味著使用Sqoop直接從原服務(wù)器抽取數(shù)據(jù),新的表結(jié)構(gòu)只能是全字符串類(lèi)型。這也就意味著原來(lái)的JDBC的查詢可能會(huì)遭遇不順,因?yàn)槠谕贿w移的表有int和date等字段,如果JDBC對(duì)字段類(lèi)型不一致的查詢不兼容的話,這事就不太好說(shuō)。
2)通過(guò)MapReduce進(jìn)行批量插入。
如果直接跑SQL文件效率會(huì)非常低,因?yàn)槭且粭l一條插入的,先不說(shuō)導(dǎo)入數(shù)據(jù)的過(guò)程,即使開(kāi)高并發(fā),服務(wù)器上的數(shù)據(jù)也難以導(dǎo)出成sql文件。因此PASS掉導(dǎo)出文件的方式,只能是直接抽取。
? ? ? ?
其他:在之前的實(shí)驗(yàn)中,我曾用12W條記錄的upsert插入sql文件進(jìn)行插入,結(jié)果在插入5W+行的時(shí)候發(fā)生了堆溢出。這說(shuō)明使用$SQOOP/bin/psql.py xxx.sql的命令時(shí)會(huì)在Jvm跑一個(gè)進(jìn)程,每個(gè)運(yùn)行腳本的插入數(shù)有限制。
因此可以考慮通過(guò)MapReduce進(jìn)行批量的插入過(guò)程,但其實(shí)只需要Map任務(wù)就可以了,相當(dāng)于自己寫(xiě)了一個(gè)特殊的Sqoop的實(shí)例,滿足這種特殊的數(shù)據(jù)抽取需求。
?
2.幾個(gè)核心的點(diǎn):
1)服務(wù)器上的數(shù)據(jù)怎么導(dǎo)出
剛才分析過(guò)了,只能通過(guò)Sqoop或者手碼MR程序
2)數(shù)據(jù)如何導(dǎo)入HBase,并且使得Phoenix能夠順利識(shí)別?
一種方法是全部字段使用字符串,然后使用HBase的put
一種方法是走Phoenix進(jìn)行插入,這么插入就必須寫(xiě)MR了
3)rowkey怎么設(shè)計(jì)?
rowkey是Phoenix表的主鍵,而且根據(jù)HBase的特性,Phoenix表按照主鍵自動(dòng)排序,這樣就存在一個(gè)問(wèn)題,如何設(shè)計(jì)rowkey?
注意:一般將時(shí)間作為rowkey的排在最前面的指標(biāo),如果不這么做,數(shù)據(jù)就完全按照ID分散了。在ID為隨機(jī)值的情況下,本來(lái)緊挨在一起的(按照時(shí)間)的數(shù)據(jù)完全分散,因此這個(gè)地方特別需要注意。
因此我將 `<CRETAE_TIME>_<DATA_ID>`做為rowkey,這對(duì)于范圍查詢是非常好的設(shè)計(jì)。
?
3.MySQL(未優(yōu)化)和Phoenix(未優(yōu)化)的性能查詢測(cè)試
PS:其實(shí)HBase的查詢性能,在數(shù)據(jù)量為百萬(wàn)時(shí),與中型數(shù)據(jù)庫(kù)Mysql是持平的,可能Mysql還會(huì)更優(yōu)秀一些。但當(dāng)數(shù)據(jù)到達(dá)千萬(wàn)的級(jí)別的時(shí)候,HBase的查詢優(yōu)勢(shì)就非常明顯了。
1)11W+條數(shù)據(jù)的測(cè)試:
1.1) 非rowkey查詢
從50000行左右隨機(jī)抽取一個(gè)ID:
不使用rowkey(相當(dāng)于不使用一級(jí)索引)進(jìn)行查詢:
如果采用rowkey進(jìn)行模糊匹配:
?
?
1.2)基于rowkey的查詢(基于CRETAE_TIME和ID字段)
從70000行左右隨機(jī)抽取一個(gè)ID和CREATE_TIME,因?yàn)槲以O(shè)計(jì)的rowkey是”<CREATE_TIME>_<ID>"的格式:
?2).百萬(wàn)級(jí)別數(shù)據(jù)量測(cè)試
通過(guò)Sqoop 從mysql向HBase遷移100W條數(shù)據(jù)(單Map Task)的時(shí)間為:
269.6587 seconds (0 bytes/sec) 不到5分鐘?
機(jī)器配置: 3G 全偽分布式 , Hadoop HBase Zookeeper主從全在一臺(tái)機(jī)器上
?
MySQL:
HBase(Phoneix):
2.1)非rowkey的查詢
?
?
?2.2) rowkey查詢
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/yosql473/p/9900596.html
總結(jié)
以上是生活随笔為你收集整理的从mysql向HBase+Phoenix迁移数据的心得总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 数据采集工具Telegraf:简介及安装
- 下一篇: 实现 通过数据库里一个字段值相等