讲备份,首先就要知道备份的种类,然后再弄清楚每种备份的操作方法。
数据备份分类:
hbase数据备份分为离线备份和在线备份两大类。
离线备份是直接备份hdfs(hadoop分布式文件系统)上的数据,它只能备份到某个具体的时间节点之前的所有数据,因为进行离线备份时,数据库要处于不工作状态,即关闭了数据库,在进行离线备份期间不接受任何读写操作,所以在进行离线备份期间直到重新启用数据库之前,数据库的一致性状态是不会改变的,当离线备份完成后,重新启动了数据库,数据库可对外提供服务了,能够对它进行读写操作了,数据库的状态才会发生改变;
那如何禁用数据库呢?
执行shutdown normal,关闭了数据库,那么就可以一次性备份该数据库的所有表;
但是有时候,需求是并不需要备份所有表,仅需要备份某数据库中的一张或者几张表,这种情况下,我们不必关闭整个数据库,要备份哪些表,我们就禁用(disable tablename)哪些表就行了,禁用了这些表,使得这些表不能对外提供服务了(但其他的表还是可以照常提供服务的),才可以开始离线备份;
但是由于离线备份对于在线业务的不友好(不友好体现在,备份时需要关闭数据库或者禁用表,不能对外提供读写服务,在线业务对数据库的依赖性强,你关闭了或者禁用了,业务执行所需要的数据就取不到了或者写不进去了),所以在0.94之后的版本就弃用了离线备份方案。
在线备份就是在进行数据备份的时候不需要关闭数据库,备份时还可以提供对外服务。
常用在线数据备份包括以下几种:
copytable、export/import(先导出到目标集群,再导入到目标集群的表中)、replication、snapshot(快照)
接下来我们详细说说这几种在线备份方案的操作:
copytable方案
copytable,顾名思义就是拷贝表或复制表,它可以拷贝表的部分或者全部内容;它可以在同一个集群内进行表的拷贝,也可以在不同集群间进行表的拷贝(比如将某个集群中的表拷贝到另一个集群上)。
进行copytable操作的前提是:必须要在目标集群上事先创建好拷贝的数据要存储的表,比如要拷贝表test1到表test2上,那么在目标集群上就必须先创建test2表,不然会报错。
copytable的用法:
通过bin/ hbase org.apache.hadoop.hbase.mapreduce.CopyTable --help查看用法
bin/hbase org.apache.hadoop.hbase.mapreduce.CopyTable [--starttime=X] [--endtime=Y] [--new.name=newtablename] [--peer.adr=ADR] tablename
对copytable用法的理解:拷贝tablename这张表上的从starttime开始到endtime结束的这部分数据到目标集群[--peer.adr=ADR]上的目标表[--new.name=newtablename]上;
从帮助文档中可以看到,copytable不仅支持时间区间的拷贝,还支持rowkey区间的拷贝,还可以更改复制数据存储的目标表的列簇名(也就是说目标表与所要复制的表的列簇名可以不相同,这个在创建时目标表时就可以确定的了,然后在进行真正的拷贝时通过--families指明新的列簇名,当然,如果目标表与复制表的元数据信息一模一样,那就不需要使用--families参数指明啦)
参数解释:
--starttime=X :执行时间范围的开始时间
--endtime=Y :执行时间范围的结束时间
ps:若--starttime=X和--endtime=Y同时使用,那就是拷贝指定时间范围内的数据;如果仅用了
--starttime=X,那就是拷贝从starttime开始之后的所有数据;如果仅用了--endtime=Y,就是拷贝从该表的第一条数据开始到endtime的所有数据;
--startrow和--stoprow用于通过rowkey指定拷贝的区间,它的理解和使用跟--starttime和--endtime一样;
(注意:这涉及到区间的问题都有开闭之分,这里的区间都是左闭右开的,即拷贝的数据包括开始的,但不包括结束的)
--new.name :指定目标表的名字
tablename:所要拷贝的表的名字
--peer.adr : 目标集群的地址(默认是指本集群,如果是本集群的拷贝,那就不用指定集群地址的,否则报错,如果是跨集群那指定的就应该是另一个集群的地址)
集群地址的格式:hbase.zookeeer.quorum:hbase.zookeeper.client.port:zookeeper.znode.parent
即zookeeper的地址:端口号:节点存储目录
使用例子:volcano01.cc.com,volcano02.cc.com,volcano03.cc.com:2181:hbase
案例演示:
同一个集群的某表的部分数据拷贝(本集群的拷贝不用指定集群地址--peer.adr,否则报错,跨集群的拷贝才要指定集群地址):
按照rowkey确定范围(所拷贝的数据包括开始的那条,不包括结束的那条,即区间是左闭右开的)
按照时间戳确定范围(区间也是左闭右开的)
同一个集群的某表的全部数据拷贝
复制表与目标表的列簇个数及列簇名不同,必需使用--families参数进行指明新表的列簇
--families参数的使用格式是:--families=oldcfname:newcfname
如果有多个列簇名不同,则格式应该是:--families=oldcfname1,oldcfname2,...:newcfname1,newcfname2,...
如果复制表与目标表的列簇名相同,不必使用--families参数
跨集群的拷贝就必须使用--peer.adr参数指定目标集群的地址了,假如有个集群地址为:
zk1,zk2,zk3:2181:hbase(我用的hbase1.2.5版本的集群地址的格式是这样写的,可能是版本的问题吧,以前的旧版本的格式是zk1,zk2,zk3:2181/hbase,一个是冒号,一个是斜杠)
那么进行跨集群拷贝的案例就应该使用如下命令:
hbase org.apache.hadoop.hbase.mapreduce.CopyTable --startrow=20180611 --stoprow=20180621 --new.name=new_t2 --peer.adr=zk1,zk2,zk3:2181:hbase t1
ps:copytable方案中同一集群de拷贝,集群中不能存在同名的表,所以在同一集群的拷贝中,都需要使用--new.name参数来指定新表的名称,但是不同集群是可以存在同名的表的,当在不同集群进行拷贝,对于同名的表可以不使用--new.name参数,不使用该参数默认表同名,否则不同名,那么就要使用参数--new.name。
export/import方案
这个数据备份方案就很浅显易懂啦,我们要进行数据备份嘛,那我们可以先把要进行备份的数据拿出来,放到某个地方,然后再将放在这个地方的数据导入到表中进行持久化;
而export/import方案将数据导出时是临时存储在hdfs上,然后再通过import导入到hbase表中
exoprt的使用方法:
使用hbase org.apache.hadoop.hbase.mapreduce.Export --help查看帮助文档
通过查看帮助文档,可以看到最简单的导出就是:
bin/hbase org.apache.hadoop.hbase.mapreduce.Export tablename hdfs路径(其他的参数都是可选的,加上[]方括号的都是指可选的)
即将某张表的数据导出到hdfs上指定路径处;
通过查看帮助文档,还可以发现,可以使用-D 来指定使用的参数来进行优化,比如使用
-D mapreduce.output.fileoutputformat.compress=true来指定输出时进行压缩;
也可以通过-D同时指定多个优化参数,如: -D mapreduce.output.fileoutputformat.compress=true -D mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.GzipCodec
(即指定输出时进行压缩并指定压缩方式)
通过查看帮助文档还可以发现,可以指定cell的版本个数(即要备份cell的多少个版本的数据),还可以指定开始时间计结束时间(有了这个时间区间,我们可以做增量备份)
案例演示:
将本集群的某张表的数据导出到hdfs的user/root/hbase_test1目录下(在本集群的导出,hdfs路径不能写绝对路径,否则报错,只有跨集群的导出才写绝对路径)
本集群的导出的hdfs路径不能写绝对路径,不能写成:hdfs:volcano01.cc.com:8020/user/root/hbase_test1
在本集群的正确的写法是:/user/root/hbase_test1
同时,请注意:导出目录必须事先不存在在hdfs上,即对于导出而言不能事先创建导出数据的存储目录,当执行导出操作时会自动创建;
import将hdfs上的数据导入表中(ps:在使用import导入数据到表中之前,表必须事先创建,这正与export操作的相反,export操作要求导出目录不能事先存在)
使用hbase org.apache.hadoop.hbase.mapreduce.Import --help查看帮助文档
通过帮助文档可知,文件导出方式为:
hbase org.apache.hadoop.hbase.mapreduce.Import tablename hdfs路径
默认情况下通过这一步import就可以直接将hdfs上的数据导入到hbase表中,它不像importcsv方式先生成Hfile文件,然后再通过-Dimport.bulk.output=hdfs结果输出路径
案例演示:
snapshot(快照)方案
要使用snapshot方案,首先要在hbase-site.xml中进行snapshot的配置,在hbase-site.xml中添加如下配置项进行配置snapshot,这个配置是开启snapshot,即开启快照功能:
<property>
<name>hbase.snapshot.enabled</name>
<value>true</value>
</property>
snapshot的使用方法:
ps:snapshot的操作都是在hbase命令行操作的
为表创建快照
snapshot '表名','快照名' (要两个参数的,参数之间以逗号隔开)
查看快照列表
通过命令list_snapshots
将快照恢复到一张新表上(ps:新表不能事先存在,否则报错)
通过命令clone_snapshot '快照名','新表名'
删除快照
通过命令delete_snapshot '快照名'
通过快照为该快照的源表进行数据恢复(ps:用快照为源表进行数据恢复之前,首先要禁用源表)
通过命令:
禁用表:disable '表名'
使用快照为源表恢复数据 :restore_snapshot '快照名' (不用带表名参数,使用这个命令默认就是恢复数据到创建这个快照的表的)
t1表的数据
使用snapshot进行恢复,恢复前先禁用
恢复后,由于之前禁用了表,所以在操作表之前应该启用表
查看恢复后的数据,可以看到多了一条rowkey为1的记录
通过ExportSnapshot将快照导出到其他集群(我尝试了将快照导到本集群,但是每次运行都失败,报错:Java heap space,所以 我认为ExportSnapshot是无法将本集群中的快照 导到本集群中的,因为,这很显然的道理嘛,本集群中已经有这个快照了,你还将这个快照再导一遍到本集群,这不是多此一举吗,所以ExportSnapshot是跨集群导出快照文件的,即将本集群的文件导出到其他集群)
ps:在linux命令行操作
通过hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -help查看帮助文档
从帮助文档中可以看到org.apache.hadoop.hbase.snapshot.ExportSnapshot 有很多参数选项,下面解释一下这些选项的意思:
-help|-h 查看帮助文档
-snapshot name 要导出的快照的名字
-copy-to name 所导到的目标集群地址hdfs://xxx:port/dir(默认是hbase-site.xml文件中配置的hbase.rootdir配置项的值)
-copy-from name 从哪个集群导出指定的snapshot文件
-overwrite 覆盖目标集群中的snapshot文件
-chuser username 修改文件的所有者,将文件所有者修改为指定的这个
-chgroup group 修改文件所属的组,将文件所属的组修改为指定的这个
-chmod mode 修改文件的权限,如chmod 700
-mappers number 指定map task的个数
-bandwidth 指定传送快照文件时的带宽大小,即限制传送速度
示例:
//将本集群的快照文件mysnapshot导出到集群 hdfs://volcano01.cc.com:8020/hbase
bin/hbase org.apache.hadoop.hbase.snapshot.tool.ExportSnapshot -snapshot mysnapshot -copy-to hdfs://volcano01.cc.com:8020/hbase
//将某个集群(不是本集群)的快照mysnapshot导到另一个集群上
bin/hbase org.apache.hadoop.hbase.snapshot.tool.ExportSnapshot -snapshot mysnapshot -copy-from hdfs://volcano02.cc.com:8020/hbase -copy-to hdfs://volcano01.cc.com:8020/hbase
将快照文件导到目标集群上之后,就可以用clone_snapshot '快照文件名' '新表名'克隆出一张新表
或者用restore_snapshot '快照文件名' 将数据恢复到新集群的表中。
相比较于export/import,ExportSnapshot更加的简便快速。
对于export/import,export要先将数据导到hdfs上,然后再通过import将数据导入到hbase中;
ExportSnapshot就是直接将hbase表的镜像导出然后就可以通过clone_snapshot或者restore_snapshot进行表的克隆或恢复。