数据插入到 table 中的方法有 :
- put , put 一次,客户端就需要向 hbase 发送一次请求, 就处理一次 ,增加了 hbase 的压力 ,插入效率低 (put 插入的值 ,是按照字典顺序排序的 , 即查询数据时 ,显示的数据是根据字典顺序排序的,而不是按照插入顺序排序).
- 使用缓存( BufferedMutator ) , 批次插入 ,数据量达到一定大小后 ,向 hbase 发送一次请求 ,因为是批量插入 ,所以插入数据时请求次数减少 ,数据插入稍高 .数据插入成功后 ,由于数据大小达不到默认设置的值 ,此时的插入的数据是存储在内存中的,还没有刷写到 hdfs 上 ,如果需要在 hbase shell客户端查看插入数据的话 ,可以在 hbase shell 客户端上手动 flush 该表单.
- BulkLoad ,大批量数据插入 .使用 inportTsv 工具, inporttsv 是 hbase 自带的一个 csv 文件 ,Hfile 文件的工具 ,能够将 csv 文件转为 Hfile 文件 ,并导入 / 发送给 regionserver (hbase 的表中) ,本质是内置的一个将 csv 文件转为转成 Hfile 文件的 mr 程序 .
flush的时机 :
- 手动强制flush (hbase shell客户端进行 flush 操作)
- 当单个 MenStore 达到系统默认阈值时,系统自动 flush ,一般是128M
- 当整个 region server 的总内存达到系统默认设置阈值时
- 当操作行为日志记录的次数达到系统默认阈值时 ,一般在100万条左右
1 put 方法
public class PutTableData {
public static void main(String[] args) throws IOException {
//获取 hbase配置对象
Configuration conf = HBaseConfiguration.create();
// 指定 zookeeper 集群的位置
conf.set("hbase.zookeeper.quorum","doit03:2181,doit04:2181,doit05:2181");
//创建连接对象
Connection connection = ConnectionFactory.createConnection(conf);
}
// 一次添加一行数据
public static void putData1(Connection connection) throws IOException {
// 获取表的操作对象
Table table = connection.getTable(TableName.valueOf("hbase01:tb_user"));
// 创建一个 put对象 ,指定一行 ,插入数据
Put put = new Put("rk002".getBytes());
put.addColumn("cf".getBytes(),"name".getBytes(),"lii".getBytes());
put.addColumn("cf".getBytes(),"gender".getBytes(),"M".getBytes());
//将数据放到表里面
table.put(put);
// 关闭操作对象
table.close();
}
// 一次添加多行数据
public static void putData2(Connection connection) {
try {
// 获取表的操作对象
Table tb_user = connection.getTable(TableName.valueOf("tb_user"));
// 添加一行数据内容
Put rk008 = new Put(Bytes.toBytes("rk008"));
rk008.addColumn("cf".getBytes(),"name".getBytes(),"hbaobao".getBytes());
rk008.addColumn("cf".getBytes(),"gender".getBytes(),"M".getBytes());
// 再添加一行数据
Put rk009 = new Put(Bytes.toBytes("rk009"));
rk009.addColumn("cf".getBytes(),"name".getBytes(),"KUU".getBytes());
rk009.addColumn("cf".getBytes(),"age".getBytes(),Bytes.toBytes(23));
// 创建一个list集合 ,用来装设置好的一行行数据
ArrayList<Put> list = new ArrayList<>();
list.add(rk008);
list.add(rk009);
// 将list集合添加到表里面
tb_user.put(list);
// 关闭连接
tb_user.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2 BufferedMutation 方法
public class PutTableData {
public static void main(String[] args) throws IOException {
//获取 hbase配置对象
Configuration conf = HBaseConfiguration.create();
// 指定 zookeeper 集群的位置
conf.set("hbase.zookeeper.quorum","doit03:2181,doit04:2181,doit05:2181");
//创建连接对象
Connection connection = ConnectionFactory.createConnection(conf);
}
//使用缓存 ,批次插入数据 ,一定大小后 ,数据才会从内存中上传到 hbase上
public static void mutation(Connection connection) throws IOException {
// 获取缓存操作表对象
BufferedMutator mutator = connection.getBufferedMutator(TableName.valueOf("hbase01:tb_user"));
// 创建一个put对象 ,指定一行数据 ,并插入内容
Put rk003 = new Put(Bytes.toBytes("rk003"));
rk003.addColumn("cf".getBytes(),"name".getBytes(),"huu".getBytes());
rk003.addColumn("cf".getBytes(),"gender".getBytes(),"F".getBytes());
Put rk004 = new Put(Bytes.toBytes("rk004"));
rk004.addColumn("cf".getBytes(),"name".getBytes(),"moo".getBytes());
// 关闭操作对象
mutator.close();
}
}
3 BulkLoad (inportTsv工具) ====> shell 客户端操作
将本地的 csv 文件变成 Hfile 文件 ,并将其上传到 hbase 上
3.1 环境准备
- hdfs / yarn--------start-all.sh
- zookeeper-------bin/zkServer.sh start (集群中的每台机器都要启动)
- hbase ------------ start-hbase.sh (==HMaster启动后,克隆一个节点开启 shell 客户端 == ==>hbase shell)
遇到的问题1 : 如果 zookeeper 服务只在集群中的一台机器上开启 ,其他机器没有开启服务的话 , 当开启 start-hbase.sh , 然后进入 hbase shell 客户端时 ,不能在客户端上执行任何命令 ,并且会提示说 “hmaster” 没有开启 .所以在使用 hbase 时 ,必须确保 zookeeper 在集群中的所有机器中都是开启的状态
遇到的问题2 : 如果 zookeeper 在集群中都开启了 ,而 hbase 的 HMaster 没有开启 ,即没有执行 “start-hbase.sh"命令 ,而是直接执行 “hbase shell” 命令 ,进入hbase shell 客户端 ,这种情况也是不能执行使用任何命令的 ,同时也会出现提示说"hmaster” 没有开启 .所以在使用 hbase 时 ,必须确保 hbase的 HMaster 是开启的状态*
3.2 在 linux 本地根目录的 root 目录下新建一个 csv 文件夹 ,并编写一个 csv 文件
[root@linux03root]# mkdir csv
[root@linux03root]# cd csv/
[root@linux03 csv]# vi user.csv
// 插入字段 ,如下
zss,18,M
lii,16,F
zww,17,M
Esc 退出编辑模式 , :wq! 保存退出
3.3 在 hdfs 上新建一个多级目录文件夹 /csv/input , 然后将本地新建的 user.csv 文件上传到 hdfs 的 /csv/output 上 ( output 文件不需要人为的建立 ,系统在导出文件时会自动生成 )
[root@linux03 csv]#hdfs dfs -rm -r /csv // 将 hdfs 上原先的 csv 文件夹删除掉
[root@linux03 csv]# hdfs dfs -mkdir -p /csv/input // 建立一个多级的文件夹
[root@doit03 csv]# hdfs dfs -ls /csv // 查看新建的 csv 文件夹
drwxr-xr-x - root supergroup 0 2020-09-03 04:02 /csv/input // 显示存在 ,创建成功
3.4 将本地的 user.csv 文件上传到 hdfs 的 /csv/input 文件夹中
[root@linux03 csv]# hdfs dfs -put user.csv /csv/input/ // 上传文件
[root@linux03 csv]# hdfs dfs -ls /csv/input/ // 查看上传结果
-rw-r--r-- 3 root supergroup 74 2020-09-03 04:08 /csv/input/user.csv // 显示上传成功
3.5 进入 hbase shell 客户端 ,新建一个 tb_user 空白表 ,有一个列族(cf)即可
[root@linux03 csv]# hbase shell
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/apps/hadoop-3.2.1/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/apps/hbase-2.2.5/lib/client-facing-thirdparty/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
HBase Shell
Use "help" to get list of supported commands.
Use "exit" to quit this interactive shell.
For Reference, please visit: http://hbase.apache.org/2.0/book.html#shell
Version 2.2.5, rf76a601273e834267b55c0cda12474590283fd4c, 2020年 05月 21日 星期四 18:34:40 CST
Took 0.0023 seconds
hbase(main):001:0> hbase(main):010:0> create 'tb_user','cf'
3.6 HDFS 集群节点服务器上执行以下shell命令( 将本地的 csv 文件转变成 Hfile 文件 )
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv
-Dimporttsv.separator=, // 使用 "," 符号分割 ,默认是 tab ,即 "\t"
-Dimporttsv.columns='HBASE_ROW_KEY,cf:name,cf:age,cf:gender' // hbase-rowkey 的设置 ,属性与 user.csv 内容相对应
-Dimporttsv.bulk.output=/csv/output tb_user /csv/input // 将 /csv/input 下的文件上传到 tb_user 上面 ,输出到 /csv/output 文件夹中
3.7 HDFS 集群节点服务器上输入指令 , enter 开始将文件加载上传( 将 Hflie 文件导入到 Hbase 中 )
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /csv/output tb_user
3.8 通过执行的日志 ,可以看到执行的底层就是 mapreduce 程序 ,执行完毕后 ,可以查看文件
// 在 hdfs 的 /csv/output 文件夹上查看 ,列族数量与 hdfs 上存储的 hbase 文件一致
-rw-r--r-- 3 root supergroup 0 2020-09-03 04:42 /csv/output/_SUCCESS
drwxr-xr-x - root supergroup 0 2020-09-03 04:49 /csv/output/cf // 根据列族的个数生成
// 在 hbase shell 客户端上查看
hbase(main):002:0> scan 'tb_user' // 查看 hbase 上的 tb_user 表内容插入情况
ROW COLUMN+CELL
baba column=cf:age, timestamp=1599079282089, value=M
baba column=cf:name, timestamp=1599079282089, value=26
huu column=cf:age, timestamp=1599079282089, value=M
huu column=cf:name, timestamp=1599079282089, value=20
lii column=cf:age, timestamp=1599079282089, value=F
lii column=cf:name, timestamp=1599079282089, value=16
luu column=cf:age, timestamp=1599079282089, value=M
luu column=cf:name, timestamp=1599079282089, value=19
mama column=cf:age, timestamp=1599079282089, value=F
mama column=cf:name, timestamp=1599079282089, value=25
poo column=cf:age, timestamp=1599079282089, value=F
poo column=cf:name, timestamp=1599079282089, value=15
zss column=cf:age, timestamp=1599079282089, value=M
zss column=cf:name, timestamp=1599079282089, value=18
zww column=cf:age, timestamp=1599079282089, value=M
zww column=cf:name, timestamp=1599079282089, value=17