Hadoop实时day21–Apache HBase
今日内容大纲
1、Apache HBase和 mapreduce整合(重要)
读写hbase表
bulkload加载数据
(file--->hfile--->bulkload--->hbase)
2、Apache HBase Hive整合(重要)
3、Apache HBase sqoop整合
mysql<---->hbase
4、HBase 预分区 + rowkey设计(重要)(重要)(重要)(重要)(重要)(重要)
rowkey是字符串 底层使用bytes[]
从左到右根据字典序比较
5、Hbase 协处理器
6、Hbase 二级索引
什么一级索引。 hbase中只有rowkey才有索引。
--------
重要扩展
1、master HA机制
2、TTL 超时时间
3、布隆过滤器 加快查询速度
概率型数据结构
HBase 和mapreduce整合
-
mapreduce天生可以和hbase整合。
-
mapreduce专门设计了两个类 用于mr和hbase的交互
-
TableMapper --负责从HBase中读数据的类
-
TableReducer– 负责把数据写入HBase中
在使用tablereducer写数据到hbase的时候 输出的v必须是put或者是delete the output value must be either a Put or a Delete instance when using the TableOutputFormat class.
-
-
需求:使用mapreduce从hbase一张表中读取数据 对数据进行处理 再把部分数据写入hbase另一张表。
将myuser这张表当中f1列族的 name 和 age 字段写入到 myuser1 这张表的 f1 列族当中去。 create 'myuser1','f1' get put scan delete
-
HBase专门封装了一个工具类 TableMapReduceUtil用于mr程序的map reduce任务的初始化。
TableMapReduceUtil.initTableMapperJob(TableName.valueOf("myuser"), scan,HBaseMrMapper.class, ImmutableBytesWritable.class, Put.class,job); TableMapReduceUtil.initTableReducerJob("myuser1",HBaseMrReducer.class,job);
-
bulkloadh功能
-
当我们使用put方式加载数据的时候 需要一条条插入进行 数据需要经过内存 磁盘 最终才能编程hfile。
-
也可以使用技术把数据首先变成hfile格式 加载移动到hbase对应的位置路径下
-
弊端:使用bulkload导入数据 不会有hlog日志产生 意味着后续数据恢复成为问题。
-
实现
-
如何把普通的文件变成hfile格式 要满足表约束。
-
使用mapreduce内置==HFileOutputFormat2==类把输出的数据变成Hfile格式
job.setOutputFormatClass(HFileOutputFormat2.class); HFileOutputFormat2.configureIncrementalLoad(job,table,connection.getRegionLocator(TableName.valueOf("myuser1")));
-
-
如何把hfile加载到hbase对应的路径下。
-
核心api
LoadIncrementalHFiles load = new LoadIncrementalHFiles(configuration); load.doBulkLoad(new Path("hdfs://node-1:8020/hbase/output_hfile2"), admin,table,connection.getRegionLocator(TableName.valueOf("myuser1")));
-
-
-
数据准备
#hdfs 路径/hbase/input/user.txt 内容如下: 0007 zhangsan 18 0008 lisi 25 0009 wangwu 20
-
HBase 和HIve整合
-
两者对比
-
hive–数据仓库
基于Hadoop的数仓。面向分析支持分析。 olap系统。 可以将结构化文件映射成为一张表 提供了基于表sql查询能力。 支持复杂的业务分析。
-
hbase–nosql数据库
基于hdfs的nosql数据库。 不支持sql 不支持复杂业务分析。不支持复杂事务,支持简单行级事务。 支持基于rowkey索引查询。 大表数据实时读写查询。
-
-
整合方式
- 创建hive表 把数据存储在hbase中。
- 创建hive外部表 映射hbase已有的表。
-
整合过程
-
添加hbase相关的jar到hive lib路径下
cd /export/servers/hbase/lib/ cp hbase-client-1.2.0-cdh5.14.0.jar hbase-hadoop2-compat-1.2.0-cdh5.14.0.jar hbase-hadoop-compat-1.2.0-cdh5.14.0.jar hbase-it-1.2.0-cdh5.14.0.jar hbase-server-1.2.0-cdh5.14.0.jar /export/servers/hive/lib/
-
修改hive的配置文件 添加zk属性
<property> <name>hive.zookeeper.quorum</name> <value>node-1,node-2,node-3</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>node-1,node-2,node-3</value> </property>
-
修改hive环境变量shell 添加hbase路径
export HADOOP_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0 export HBASE_HOME=/export/servers/hbase export HIVE_CONF_DIR=/export/servers/hive/conf
-
-
核心api语法
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf:name,cf:score") TBLPROPERTIES("hbase.table.name" ="hbase_hive_score")
HBase和sqoop整合
-
从mysql到hbase
bin/sqoop import \ --connect jdbc:mysql://192.168.1.5:3306/library \ --username root \ --password admin \ --table book \ --columns "id,name,price" \ #列 --column-family "info" \ #列族名称 --hbase-create-table \ #在hbase中创建表 --hbase-row-key "id" \ #rowkey对应着表的字段 --hbase-table "hbase_book" \ #表名 --num-mappers 1 \ --split-by id
-
从hbase到mysql
- 思路:Hbase→hive 外部表→hive 内部表→通过 sqoop→mysql
- 注意:位于mysql中表要提前存在。
#step1 创建hive外部表映射hbase表 CREATE EXTERNAL TABLE hbase2mysql (id int,name string,price int) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,info:name, info:price" ) TBLPROPERTIES( "hbase.table.name" = "hbase_book", "hbase.mapred.output.outputtable" = "hbase2mysql"); #step2 创建hive内部表 把外部表数据插入到内部表中 CREATE TABLE hbase2mysqlin(id int,name string,price int); insert overwrite table hbase2mysqlin select * from hbase2mysql; #step3 使用sqoop把内部表的数据导出到mysql中 bin/sqoop export -connect jdbc:mysql://node-1:3306/library \ -username root -password hadoop -table book \ -export-dir /user/hive/warehouse/hbase2mysqlin \ --input-fields-terminated-by '\001' \ --input-null-string '\\N' --input-null-non-string '\\N' #sqoop参数 --input-null-string '\\N' --input-null-non-string '\\N' 对于hive的空值数据 不管是字符串类型的空值 还是非字符串类型的空值 在导出到mysql的时候 统一的使用\N表示空 避免null和“null”歧义。
HBase 预分区、rowkey设计
-
rowkey特性
-
rowkey是字符串类型 最大长度64K。
-
底层是以二级制==字节数组byte[]==形式存储的。
-
默认根据字节数组**索引字典序**排序。
从左往右逐位比较 如果相等继续比较下一位。 001 0010 001| 002 00a #底层是通过ASCII 码表进行比较 http://ascii.911cha.com/
-
-
HBase预分区
-
默认region split规则有什么不好的地方。
- 拆分规则导致region大小不相等 负载不均衡。
- 默认的rowkey排序会导致某块区域集中访问 热点问题。
-
默认情况下创建表的时候只有一个分区 范围是:
[-oo , +oo]
- 意味着数据只要put 就写入该分区中 直到满足条件进行region split拆分
- 分区的关键之处是分区标识键:Start Key End Key
-
hbase支持在创建表的时候 指定分区的个数 提取创建好分区 这叫做预分区。
-
如何预分区
-
把分区标识写在文件中 建表的时候加载文件。
cd /export/servers/ vim splits.txt aa| bb| cc| dd| create 'staff3','partition2',SPLITS_FILE =>'/export/servers/splits.txt'
-
建表手动写
create 'staff','info' ,SPLITS =>['1000','2000','3000','4000']
-
-
预分区创建好之后 还必须结果rowkey设计 否则将失去意义。
-
-
rowkey设计原则
-
官方指导标准:https://hbase.apache.org/book.html#rowkey.design
-
唯一原则
rowkey是不同行数据之间的唯一标识。类似于主键 不能重复的。
-
rowkey长度原则
理论上rowkey最高支持64K。实际中并不是越长越好,因为rowkey最终也是要存储在hfile总的。
-
散列原则
尽量避免rowkey在一台regionserver上,造成读写的热点问题。尽量打散分布在各个不同机器上,配合预分区技术实现负载均衡。
-
在追求散列原则的同时 追求集中原则。
追求散列的目的是避免热点问题。 追求集中的目的是保证业务查询相关的数据尽量集中在一起 避免多台机器查询。
-
散列实现方式
-
加盐(Salting)–random
在rowkey前加上随机字符串等符号。 foo0001 foo0002 foo0003 foo0004 加盐之后 a-foo0003 b-foo0001 c-foo0004 d-foo0002 a-foo0003 b-foo0001 比如:分区表示 a| b| c| d|
-
==哈希(Hashing)==重点
使用hash等算法对数据进行取值 只要数据不变 得出的结果是一样的。 哈希方法: hash(手机号+月+天) % 4 = 余数就是前缀 hash(13888888888+2018+1031) = 1 hash(13888888888+2018+1101) = 3 hash(13888888888+2018+1101) = 3 hash(13888888888+2018+1102) = 4
-
反转
原始数据: 13888888888 13999999999 13777777777 13666666666 反转之后: 88888888831 99999999931 77777777731 66666666631
-
时间戳反转
-
-
-
-
案例:中国联不通–手机上网流量详单
-
需求:提供用户查询指定某一天上网详细记录。 按天查询。
-
预分区
# 根据业务和数据量 确定hbase表分区个数 100个 region # 确定分区标识键 starkey stookey 00| 01| 02| 03| ... 98|
-
rowkey设计
-
指导标准:追求散列的同时 追求数据集中。
- 散列:不同用户不同天上网记录分散开
- 集中:同一个用户同一天上网记录集中一起 便于查询。
-
设计hash方法
hash(手机号+天) % 99
-
原始数据
用户:18888888888 起始时间 通信地点 网络类型 计费类型 总流量/KB 通信费 2020-08-10 00:25:29 sh 4G 免费 2225 0.0 2020-08-10 11:43:49 nj 7G 免费 5566 0.0 2020-08-12 03:25:52 dj 2G 免费 3152 0.0 2020-08-13 04:23:29 sh 4G 免费 445 0.0
-
rowkey的前缀
#step1 18888888888+2020-08-10 通过hash方法计算前缀 hash(18888888888+2020-08-10) % 99 = 25 rowkey 25-手机号+2020-08-10+00:25:29 sh 4G 免费 2225 0.0 25-手机号+2020-08-10+11:43:49 nj 7G 免费 5566 0.0 32-手机号+2020-08-12+03:25:52 dj 2G 免费 3152 0.0 48-手机号+2020-08-13+04:23:29 sh 4G 免费 445 0.0
-
scan查询的时候如何设置查询条件
# 用户操作:查询 18888888888 2020-08-10上网通信记录。 # step1: 通过页面表单拿取到当前操作的用户手机号 查询天条件 18888888888 2020-08-10 # step2: 使用哈希方法计算前缀值 hash(18888888888+2020-08-10) % 99 = 25 # step3:封装scan查询条件 Scan scan = new Scan(); scan.setStartRow("25-手机号+2020-08-10") #有比没有打 scan.setStopRow("25-手机号+2020-08-10|") #| 老子倒数第三大
-
-
Hbase 协处理器
-
概念
- 协助帮助用户进行某种操作的处理器技术。
-
背景知识
- 触发器
- 相当于在数据库上绑定一些函数 当用户操作行为满足条件 触发函数的执行。
- 对应hbase来说 给put delete进行绑定
- 存储过程
- 相当于定义一个函数。需要用户手动调用才会在服务器上执行相关的逻辑。
- 触发器
-
hbase协处理器分类
- observer --触发器 和具体操作绑定
- endpoint–存储过程 需要用户手动调用执行。
-
hbase协处理器都是在服务端执行的。
-
栗子:observer 使用。
-
需求:给一张表绑定协处理器 当有put数据插入的时候 通过协处理器把数据复制一份到另一张表。
-
创建表
create 'proc1','info' create 'proc2','info' #没有挂载协处理器之前 表元数据样子 hbase(main):041:0> describe 'proc1' {NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALS E', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCAC HE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
-
写类继承BaseRegionObserver
-
把协处理器打成一个jar 注意:此时打包只需要把自己的代码打包即可 把pom中打包插件注释掉。
-
把打好jar上传到hdfs的目录下
cd /export/servers mv example-hbase-1.0.jar processor.jar hdfs dfs -mkdir -p /processor hdfs dfs -put processor.jar /processor
-
给指定的表挂载协处理器
alter 'proc1',METHOD => 'table_att','Coprocessor'=>'hdfs://node-1:8020/processor/processor.jar|cn.itcast.hbase.MyCp|1001|' Coprocessor'=>'hdfs jar路径|主类|1001| 数字是优先级 一个表可以挂载多个协处理器 数字越小优先级越高
-
-
晚上练习:https://hbase.apache.ocp_examplerg/book.html#
HBase 重要扩展
-
master HA机制
-
master在哪台机器运行是如何决定的?
在哪里启动 哪台机器就是master 当使用脚本一键的时候 在运行脚本的机器上就是master.
-
如果多个机器都启动master怎么办?
谁先启动去zk注册节点/master 谁就是master 其他的自动成为备份master. hbase支持多主 当active master出现故障之后 其他备份收到zk通知 去抢夺节点。谁抢到谁就是新的master.
-
如果想在一键启动的时候 自动帮助我们启动备份master 可以在conf下创建一个文件
backup-masters node-2 node-3
-
-
HBase TTL
-
概念:Time To Live 生存时间值。
-
在hbase中 默认情况下数据 TTL是永久的。除非手动删除 否则一致存在。
-
可以在建表的时候 或者修改表 让TTL时间生效 倒计时结束之后 数据将会被自动删除。
TTL => 'FOREVER' create 't_9', {NAME => 'f1', VERSIONS => 1, TTL => 10} #单位是s TTL => '10 SECONDS',
-
应用场景
- 秒杀场景
- 支付验证码
- 扩展:redis也有TTL 基于内存nosql数据库。 它的TTL功能更好哦。
-
-
HBase 布隆过滤器
- 是一种概率型数据结构
- 可以判断某个数据一定不在 但是不能判断数据是否一定在。
今日作业
- hbase和mapreduce、hive 、sqoop集成。
- 预分区和rowkey设计 吃透概念 举一反三。
- 散列又集中
- 笔记上概率 扩展知识 查缺补漏。
- 预习kafka MQ。