目录
1.5 Kafka
1.5.0 Kafka基本组成:(重点)
1.5.1 kafka工作流程:(重点)
1.5.2 Kafka压测
1.5.3 Kafka的机器数量
1.5.4 Kafka的日志保存时间
1.5.5 Kafka的硬盘大小
1.5.6 Kafka监控
1.5.7 Kakfa分区数
1.5.8 副本数设定
1.5.9 多少个Topic
1.5.13 Kafka中数据量计算
1.5.11 Kafka的ISR副本同步队列(重点)
1.5.12 Kafka分区分配策略(重点)
1.5.16 Kafka幂等性
1.5.18 Kafka数据重复(重点)
1.5.14 Kafka挂掉
1.5.10 Kafka丢不丢数据(重点)
1.5.15 Kafka消息数据积压,Kafka消费能力不足怎么处理?
1.5.19 Kafka参数优化
1.5.20 Kafka高效读写数据(重点)
1.5.17 Kafka事务(重点)
1.5.21 Kafka支持传输
1.5.22 Kafka过期数据清理
1.5.23 Kafka可以按照时间消费数据
1.5.24 Zookeeper中存储kafka哪些信息(重点)
1.5.25 kafka和RabbitMQ区别:
Zookeeper
角色及功能:(重点)
工作原理:
选举机制:(重点)
监听原理:(重点)
客户端命令行操作
为什么Zookeeper集群数一般为奇数:
Flume
1. 知道 Flume 的 Channel 是啥吗
2. 介绍⼀下 Memory Channel
3. 说说 File Channel
4. 说说 Kafka Channel
5. 介绍⼀下 Kafka ⼏种 Sink
6. 说说 Flume 的拦截器
7. 介绍⼀下什么是选择器
8. 了解 Flume 的负载均衡和故障转移吗
Hbase
1.7.2 RowKey设计原则
1.7.3 RowKey如何设计
1.HBase的操作数据的步骤
2.HDFS和HBase各⾃使⽤场景(重点)
3.热点现象及解决办法。(重点)
4.RowKey的设计原则?(重点)
5.hbase.hregion.max.filesize应该设置多少合适
6.autoflush=false的影响
7对于传统关系型数据库中的⼀张table,在业务转换到hbase上建模时,从性能的⾓度应该 如何设置family和qualifier呢?
8.Hbase⾏健/列族的概念,物理模型,表的设计原则?
9.HBase存储单元Cell?(重点)
10.说说HBase物理模型?(重点)
11.HBase的客户端Client?
12.介绍HBase⼆级索引?
13.每天百亿数据存⼊HBase,如何保证数据的存储正确和在规定的时间⾥全部录⼊完毕,不残留数据?
14.你知道哪些HBase优化⽅法(重点)
15.HRegionServer宕机如何处理?
16.HBase简单读写流程
17.HBase和Hive的对⽐(重点)
18.HBase与传统关系型数据库(如MySQL)的区别(重点)
19.什么时候适合使⽤HBase(应⽤场景)?(重点)
20.Client会缓存.META.的数据,该数据更新了怎么办?
21.请描述如何解决Hbase中region太⼩和region太⼤带来的冲突?
22.解释下 hbase 实时查询的原理(重点)
23.HBase 宕机如何处理?
1.5 Kafka
1.5.0 Kafka基本组成:(重点)
producer、comsumer、broker、zookeeper
1.5.1 kafka工作流程:(重点)
kafka中消息以topic分类,生产者生产消息,消费者消费消息,都是面向topic的
topic是逻辑的概念,而partition是物理的概念,每个partition对应于一个log文件,
该log文件中存储的就是producer生产的数据,Producer生产的数据会不断的追加到该log的末端,且每条数据都有自己的offset,
消息者组中每个消费者,都会实时记录自己消费到哪个offset,以便出错时,从上次的位置继续消费。
1.5.2 Kafka压测
Kafka官方自带压力测试脚本(kafka-consumer-perf-test.sh、kafka-producer-perf-test.sh)。Kafka压测时,可以查看到哪个地方出现了瓶颈(CPU,内存,网络IO)。一般都是网络IO达到瓶颈。
1.5.3 Kafka的机器数量
Kafka机器数量=2*(峰值生产速度*副本数/100)+1
1.5.4 Kafka的日志保存时间
3天(默认7天,生产环境下通常3天)
1.5.5 Kafka的硬盘大小
每天的数据量*3天/70%
1.5.6 Kafka监控
公司自己开发的监控器;
开源的监控器:KafkaManager、KafkaMonitor、KafkaEagle
1.5.7 Kakfa分区数
1)创建一个只有1个分区的topic
2)测试这个topic的producer吞吐量和consumer吞吐量。
3)假设他们的值分别是Tp和Tc,单位可以是MB/s。
4)然后假设总的目标吞吐量是Tt,那么分区数=Tt / min(Tp,Tc)
例如:producer吞吐量=20m/s;consumer吞吐量=50m/s,期望吞吐量100m/s;
分区数=100 / 20 =5分区
https://blog.csdn.net/weixin_42641909/article/details/89294698
分区数一般设置为:3-10个
1.5.8 副本数设定
一般我们设置成2个或3个,很多企业设置为2个。
1.5.9 多少个Topic
通常情况:多少个日志类型就多少个Topic。也有对日志类型进行合并的。
1.5.13 Kafka中数据量计算
每天总数据量100g,每天产生1亿条日志, 10000万/24/60/60=1150条/每秒钟
平均每秒钟:1150条
低谷每秒钟:50条
高峰每秒钟:1150条*(2-20倍)=2300条-23000条
每条日志大小:0.5k-2k(取1k)
每秒多少数据量:2.0M-20MB
ISR(In-Sync Replicas),副本同步队列。ISR中包括Leader和Follower。如果Leader进程挂掉,会在ISR队列中选择一个服务作为新的Leader。有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,在0.10版本移除了replica.lag.max.messages参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把Follower剔除出ISR,存入OSR(Outof-Sync Replicas)列表,新加入的Follower也会先存放在OSR中。
1.5.12 Kafka分区分配策略(重点)
在 Kafka内部存在两种默认的分区分配策略:Range和 RoundRobin。
Range是默认策略。Range是对每个Topic而言的(即一个Topic一个Topic分),首先对同一个Topic里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。然后用Partitions分区的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。
例如:我们有10个分区,两个消费者(C1,C2),3个消费者线程,10 / 3 = 3而且除不尽。
C1-0 将消费 0, 1, 2, 3 分区
C2-0 将消费 4, 5, 6 分区
C2-1 将消费 7, 8, 9 分区
第一步:将所有主题分区组成TopicAndPartition列表,然后对TopicAndPartition列表按照hashCode进行排序,最后按照轮询的方式发给每一个消费线程。
1.5.16 Kafka幂等性
Producer的幂等性指的是当发送同一条消息时,数据在Server端只会被持久化一次,数据不丟不重,但是这里的幂等性是有条件的:
1)只能保证Producer在单个会话内不丟不重,如果Producer出现意外挂掉再重启是无法保证的(幂等性情况下,是无法获取之前的状态信息,因此是无法做到跨会话级别的不丢不重)。
2)幂等性不能跨多个Topic-Partition,只能保证单个Partition内的幂等性,当涉及多个 Topic-Partition时,这中间的状态并没有同步。
1.5.18 Kafka数据重复(重点)
幂等性+ack-1+事务
Kafka数据重复,可以再下一级:SparkStreaming、redis或者hive中dwd层去重,去重的手段:分组、按照id开窗只取第一个值;
1.5.14 Kafka挂掉
1)Flume记录
2)日志有记录
3)短期没事
重启即可
Ack=0,相当于异步发送,消息发送完毕即offset增加,继续生产。
Ack=1,leader收到leader replica 对一个消息的接受ack才增加offset,然后继续生产。
Ack=-1,leader收到所有replica 对一个消息的接受ack才增加offset,然后继续生产。
默认ack=1
1.5.15 Kafka消息数据积压,Kafka消费能力不足怎么处理?
1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。
1)Broker参数配置(server.properties)
1、网络和io操作线程配置优化
# broker处理消息的最大线程数(默认为3)
num.network.threads=cpu核数+1
# broker处理磁盘IO的线程数
num.io.threads=cpu核数*2
2、log数据文件刷盘策略
# 每当producer写入10000条消息时,刷数据到磁盘
log.flush.interval.messages=10000
# 每间隔1秒钟时间,刷数据到磁盘
log.flush.interval.ms=1000
3、日志保留策略配置
# 保留三天,也可以更短 (log.cleaner.delete.retention.ms)
log.retention.hours=72
4、Replica相关配置
offsets.topic.replication.factor:3
# 这个参数指新创建一个topic时,默认的Replica数量,Replica过少会影响数据的可用性,太多则会白白浪费存储资源,一般建议在2~3为宜。
2)Producer优化(producer.properties)
buffer.memory:33554432 (32m)
#在Producer端用来存放尚未发送出去的Message的缓冲区大小。缓冲区满了之后可以选择阻塞发送或抛出异常,由block.on.buffer.full的配置来决定。
compression.type:none
#默认发送不进行压缩,推荐配置一种适合的压缩算法,可以大幅度的减缓网络压力和Broker的存储压力。
4)Kafka内存调整(kafka-server-start.sh)
默认内存1个G,生产环境尽量不要超过6个G。
export KAFKA_HEAP_OPTS="-Xms4g -Xmx4g"
1.5.20 Kafka高效读写数据(重点)
1)Kafka本身是分布式集群,同时采用分区技术,并发度高。
2)顺序写磁盘
Kafka的producer生产数据,要写入到log文件中,写的过程是一直追加到文件末端,为顺序写。官网有数据表明,同样的磁盘,顺序写能到600M/s,而随机写只有100K/s。这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。
3)零复制技术
要拷贝的数据直接走内核,不经过应用层了。
1.5.17 Kafka事务(重点)
Kafka从0.11版本开始引入了事务支持。事务可以保证Kafka在Exactly Once语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。
1)Producer事务
为了实现跨分区跨会话的事务,需要引入一个全局唯一的Transaction ID,并将Producer获得的PID和Transaction ID绑定。这样当Producer重启后就可以通过正在进行的Transaction ID获得原来的PID。
为了管理Transaction,Kafka引入了一个新的组件Transaction Coordinator。Producer就是通过和Transaction Coordinator交互获得Transaction ID对应的任务状态。Transaction Coordinator还负责将事务所有写入Kafka的一个内部Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。
2)Consumer事务
上述事务机制主要是从Producer方面考虑,对于Consumer而言,事务的保证就会相对较弱,尤其时无法保证Commit的信息被精确消费。这是由于Consumer可以通过offset访问任意信息,而且不同的Segment File生命周期不同,同一事务的消息可能会出现重启后被删除的情况。
1.5.21 Kafka支持传输
kafka对于消息体的大小默认为单条最大值是1M但是在我们应用场景中, 常常会出现一条消息大于1M,如果不对kafka进行配置。则会出现生产者无法将消息推送到kafka或消费者无法去消费kafka里面的数据, 这时我们就要对kafka进行以下配置:server.properties
所以如果传输的日志文件是2M,那么kafka就会卡死。需要重新配置参数。
1.5.22 Kafka过期数据清理
保证数据没有被引用(没人消费他)
日志清理保存的策略只有delete和compact两种
log.cleanup.policy=delete启用删除策略
log.cleanup.policy=compact启用压缩策略
1.5.23 Kafka可以按照时间消费数据
Map<TopicPartition, OffsetAndTimestamp> startOffsetMap = KafkaUtil.fetchOffsetsWithTimestamp(topic, sTime, kafkaProp);
1.5.24 Zookeeper中存储kafka哪些信息(重点)
Kafka的broker的brokerid,comsumer,topics,partitions,副本信息
注意,zookeeper里唯独不存kafka的生产者的信息
1.5.25 kafka和RabbitMQ区别:
1、RabbitMQ,遵循AMQP协议,由内在高并发的erlanng语⾔开发,用在实时的对可靠性要求比较高的消息传递上(有消息确认机制)。
2、kafka是Linkedin于2010年12月份开源的消息发布订阅系统,它主要用于处理活跃的流式数据,大数据量的数据处理上(无消息确认机制,但吞吐量高),kafka用zk做集群负载均衡。
Zookeeper
角色及功能:(重点)
Leader+Learner(Follower+observer)
Leader:发起投票和决议,更新系统状态
Follower:接收客户端请求饼返回响应,参与投票
Observer:接受客户端连接,将写操作转发给L饿啊的人,不参与投票,只同步Leader
工作原理:
zookeeper=文件系统+通知机制
核心是原子广播 ----> zab协议(恢复模式和广播模式)
恢复模式:当服务启动或Leader崩溃时进入恢复模式
广播模式:进行选举,当有了Leader且大多数server与leader同步时进入广播模式。若此时再加入一个节点,会在恢复模式下启动。广播模式需要proposal被按顺序处理——递增的事务id(zxid)+paxos算法(Master编写了个全局写队列,所有写操作必须放入到该队列编号,一旦发现编号执行顺序错乱,立即自动停止并重启同步过程)
选举机制:(重点)
半数通过原则
每个server启动后都询问其他server投给谁
每个server都回复投给自己饼附上自己最大的zxid
每个server计算出收到的最大的zxid并将其附带的server信息设为下一次要投票的对象
票数最多且已过半的server设为leader
监听原理:(重点)
客户端命令行操作
命令基本语法 | 功能描述 |
help | 显示所有操作命令 |
ls path [watch] | 使用 ls 命令来查看当前znode中所包含的内容 |
ls2 path [watch] | 查看当前节点数据并能看到更新次数等数据 |
create | 普通创建 -s 含有序列 -e 临时(重启或者超时消失) |
get path [watch] | 获得节点的值 |
set | 设置节点的具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
rmr | 递归删除节点 |
为什么Zookeeper集群数一般为奇数:
3台和4台的容灾能力一样。zookeeper集群最少3台。
Flume
应用场景:将日志数据信息手机并移交到Hadoop/Kafka平台上去分析
构成:source 、Channel、Sink
事件Agent是 Flume内部传输的基本单元
1. 知道 Flume 的 Channel 是啥吗
1. Channel
被设计为
Event
中转临时缓冲区,存储
Source
收集并且没有被 Sink 读取的
Event
,为平衡
Source
收集和
Sink
读取的速度,可视为
Flume 内部的消息队列。
2. Channel
线程安全并且具有事务性,⽀持
Source
写失败写,和
Sink
读失败重复读的操作。常⻅的类型包括 Memory Channel
,
File Channel
,
Kafka Channel
。
2. 介绍⼀下 Memory Channel
读写速度快,但是存储数据量⼩,
Flume
进程挂掉、服务器停机或者重启都
会导致数据丢失。资源充⾜、不关⼼数据丢失的场景下可以⽤。
3. 说说 File Channel
将
event
写⼊磁盘⽂件,与
Memory Channel
相⽐存储容量⼤,⽆数据丢失
⻛险。
File Channel
数据存储路径可以配置多磁盘⽂件路径,通过磁盘并⾏写⼊ 提⾼ File Channel
性能。
Flume
将
Event
顺序写⼊到
File Channel
⽂件的末尾。
可以在配置⽂件中通过设置
maxFileSize
参数配置数据⽂件⼤⼩,当被写⼊的⽂
件⼤⼩达到上限的时候,
Flume
会重新创建新的⽂件存储写⼊
Event
。当⼀个已
经关闭的只读数据⽂件的
Event
被读取完成,并且
Sink
已经提交读取完成的事
务,则
Flume
把存储该数据的⽂件删除。
4. 说说 Kafka Channel
Memory Channel 有很⼤的丢数据⻛险,⽽且容量⼀般
,
File Channel
虽然
能缓存更多的消息,但如果缓存下来的消息还没写⼊
Sink
,此时
Agent
出现故
障则
File Channel
中的消息⼀样不能被继续使⽤,直到该
Agent
恢复。⽽
Kafka Channel 容量⼤,容错能⼒强。
有了
Kafka Channel
可以在⽇志收集层只配置
Source
组件和
Kafka
组件,
不需要再配置
Sink
组件,减少了⽇志收集层启动的进程数,有效降低服务器内 存、磁盘等资源的使⽤率。⽽⽇志汇聚层,可以只配置 Kafka Channel
和
Sink
,不需要再配置
Source
。
kafka.consumer.auto.offset.reset
,当
Kafka
中没有
Consumer
消费的初始
偏移量或者当前偏移量在
Kafka
中不存在(⽐如数据已经被删除)情况下
Consumer
选择从
Kafka
拉取消息的⽅式,
earliest
表示从最早的偏移量开始拉
取,
latest
表示从最新的偏移量开始拉取,
none
表示如果没有发
Consumer 组之前拉取的偏移量则抛出异常。
5. 介绍⼀下 Kafka ⼏种 Sink
1.
HDFS Sink
:
将
Event
写⼊
HDFS
⽂件存储,能够有效⻓期存储⼤量数
据。
2.
Kafka Sink
: Flume
通过
Kafka Sink
将
Event
写⼊到
Kafka
中的主题,其
他应⽤通过订阅主题消费数据。
kafka.producer.acks
可以设置
Producer
端
发送消息到
Broker
之后不需要等待
Broker
返回成功送达的信号。
0
表示
Producer
发送消息到
Broker
之后不需要等待
Broker
返回成功送达的信
号,这种⽅式吞吐量⾼,但存在丢失数据的⻛险。
1
表示
Broker
接收到消息
成功写⼊本地
log
⽂件后向
Producer
返回成功 接收的信号,不需要等待所
有的
Follower
全部同步完消息后再做回应,这种⽅式在数据丢失⻛险和吞
吐量之间做了平衡。
-1
表示
Broker
接收到
Producer
的消息成功写⼊本地
log
并且等待所有的
Follower
成功写⼊本地
log
后向
Producer
返回成功接
收的信号,这种⽅式能够保证消息不丢失,但是性能最差(层层递进)。
6. 说说 Flume 的拦截器
Source 将 Event 写⼊到 Channel 之前可以使⽤拦截器对 Event 进⾏各种形
式的处理
,
Source
和
Channel
之间可以有多个拦截器,不同拦截器使⽤不同的 规则处理 Event
,包括时间、主机、
UUID
、正则表达式等多种形式的拦截器。
7. 介绍⼀下什么是选择器
Source
发送的
Event
通过 Channel 选择器来选择以哪种⽅式写⼊到 Channel
中
,
Flume
提供三种类型
Channel
选择器,分别是复制、复⽤和⾃定义选择
器。
1.
复制选择器
:
⼀个
Source
以复制的⽅式将⼀个
Event
同时写⼊到多个
Channel
中,不同的
Sink
可以从不同的
Channel
中获取相同的
Event
,⽐
如⼀份⽇志数据同时写
Kafka
和
HDFS
,⼀个
Event
同时写⼊两个 Channel,然后不同类型的
Sink
发送到不同的外部存储。
2.
复⽤选择器
:
需要和拦截器配合使⽤,根据
Event
的头信息中不同键值数
据来判断
Event
应该写⼊哪个
Channel
中。
8. 了解 Flume 的负载均衡和故障转移吗
⽬的是为了提⾼整个系统的容错能⼒和稳定性。简单配置就可以轻松实现,
⾸先需要设置
Sink
组,同⼀个
Sink
组内有多个⼦
Sink
,不同
Sink
之间可以配 置成负载均衡或者故障转移。
Hbase
1.7.2 RowKey设计原则
1)rowkey长度原则
2)rowkey散列原则
3)rowkey唯一原则
1.7.3 RowKey如何设计
1)生成随机数、hash、散列值
2)字符串反转
1.HBase的操作数据的步骤
1
、
Hbase
写数据过程:
Client写⼊
->
存⼊
MemStore
,⼀直到
MemStore
满
-> Flush
成⼀个
StoreFile
,直⾄增长到⼀定阈值
->
出发
Compact 合并操作 ->
多个
StoreFile
合并成⼀个
StoreFile
,同时进⾏版本合并和数据删除
->
当
StoreFiles Compact
后,逐步形成越来越 ⼤的StoreFile ->
单个
StoreFile
⼤⼩超过⼀定阈值后,触发
Split
操作,把当前
Region Split
成
2
个
Region
,
Region
会下线,新 Split出的
2
个孩⼦
Region
会被
HMaster
分配到相应的
HRegionServer
上,使得原先
1
个
Region
的压⼒得以分流到
2
个
Region
上。
由此过程可知,HBase只是增加数据,有所得更新和删除操作,都是在
Compact
阶段做的,所以,⽤户写操作只需要进⼊到内存即可⽴即返回,从⽽保证I/O
⾼性能。
2
、
Hbase
读数据:
client->zookeeper->.ROOT->.META->
⽤户数据表
zookeeper
记录了
.ROOT
的路径信息(
root
只有⼀个region
),
.ROOT
⾥记录了
.META
的
region
信息, (
.META
可能有多个
region
),
.META
⾥⾯记录了
region
的信息。
2.HDFS和HBase各⾃使⽤场景(重点)
⾸先⼀点需要明⽩:Hbase是基于HDFS来存储的。
HDFS
:
(1)
⼀次性写⼊,多次读取。
(2)
保证数据的⼀致性。
(3)
主要是可以部署在许多廉价机器中,通过多副本提⾼可靠性,提供了容错和恢复机制。
HBase
:
(1)
瞬间写⼊量很⼤,数据库不好⽀撑或需要很⾼成本⽀撑的场景。
(2)
数据需要长久保存,且量会持久增长到⽐较⼤的场景
(3)
HBase
不适⽤与有
join
,多级索引,表关系复杂的数据模型
(4)
⼤数据量 (
100s TB
级数据) 且有快速随机访问的需求。
如:淘宝的交易历史记录。数据量巨⼤⽆容置疑,⾯向普通⽤户的请求必然要即时响应。
(5)
容量的优雅扩展
⼤数据的驱使,动态扩展系统容量。例如:
webPage DB
。
(6)
业务场景简单,不需要关系数据库中很多特性(例如交叉列、交叉表,事务,连接等等)
(7)
优化⽅⾯:合理设计
rowkey
。
3.热点现象及解决办法。(重点)
1. 热点现象:
⼤量的client直接访问集群的⼀个或极少数个节点(访问可能是读,写或者其他操作)
。⼤量访问会使热点region所在的单个机器超出⾃⾝承受能
⼒,引起性能下降甚⾄region不可⽤,这也会影响同⼀个RegionServer上的其他region,由于主机⽆法服务其他region的请求。
某个⼩的时段内,对HBase的读写请求集中到极少数的
Region
上,导致这些
region
所在的
RegionServer
处理请求量骤增,负载量明显偏⼤,⽽其他的RgionServer
明显空闲。
2. 热点现象出现的原因:
HBase
中的⾏是按照
rowkey
的字典顺序排序的,这种设计优化了
scan
操作,可以将相关的⾏以及会被⼀起读取的⾏存取在临近位置,便于scan
。然⽽
糟糕的rowkey设计是热点的源头
。 设计良好的数据访问模式以使集群被充分,均衡的利⽤。
3. 热点现象解决办法
:为了避免写热点,设计
rowkey
使得不同⾏在同⼀个
region
,但是在更多数据情况下,数据应该被写⼊集群的多个region
,⽽不是⼀个。常见的⽅法有以下这些:
a. 加盐
:在
rowkey
的前⾯
增加随机数
,使得它和之前的
rowkey
的开头不同。分配的前缀种类数量应该和你想使⽤数据
分散到不同的
region
的数量⼀致。加盐之后的
rowkey
就会根据随机⽣成的前缀分散到各个
region
上,以避免热点。
b.
哈希
:哈希可以使负载分散到整个集群,但是读却是可以预测的。使⽤确定的哈希可以让客户端重构完整的rowkey,可以使⽤
get
操作准确获取某⼀个⾏数据
c. 反转:
第三种防⽌热点的⽅法时反转固定长度或者数字格式的
rowkey
。这样可以使得
rowkey
中经常改变的部分(最没有意义的部分)放在前⾯。这样可以有效的随机rowkey
,但是牺牲了
rowkey
的有序性。
反转rowkey的例⼦以⼿机号为rowkey,将⼿机号反转后的字符串作为rowkey
,这样的就避免了以⼿机号那样⽐较固定开头导致热点问题
d.
时间戳反转
:
⼀个常见的数据处理问题是快速获取数据的最近版本,使⽤反转的时间戳作为
rowkey
的⼀部分对这个问题⼗分有⽤,可以⽤ Long.Max_Value - timestamp
追加到
key
的末尾,例如
[
key
][
reverse_timestamp
] , [
key
]
的最
新值可以通过
scan
[
key
]
获得
[
key
]
的第⼀条记录,因为
HBase
中
rowkey
是有序的,第⼀条记录是最后录⼊的数据。
i. ⽐如需要保存⼀个⽤户的操作记录,按照操作时间倒序排序,在设计
rowkey
的时候,可以这样设计
[
userId
反转
]
[
Long.Max_Value - timestamp
]
,在查询⽤户的所有操作记录数据的时候,直接指定反转后的
userId
,
startRow
是
[
userId
反转
][
000000000000
],
stopRow
是
[
userId
反转
][
Long.Max_Value - timestamp
]
ii. 如果需要查询某段时间的操作记录,
startRow
是
[
user
反转
][
Long.Max_Value -
起始时间
]
,
stopRow
是
[
userId 反转][
Long.Max_Value -
结束时间
]
e.
HBase
建表预分区
:创建
HBase
表时,就预先根据可能的
RowKey
划分出多个
region
⽽不是默认的⼀个,从⽽可以将 后续的读写操作负载均衡到不同的region
上,避免热点现象。
4.RowKey的设计原则?(重点)
1. 总的原则
:避免热点现象,提⾼读写性能;
2. 长度原则
:
rowkey
是⼀个⼆进制码流,可以是任意字符串,最⼤长度
64kb
,实际应⽤中⼀般为
10-100bytes
,以
byte
[]
形式保存,⼀般设计成定长。
建议越短越好,不要超过16个字节
,原因如下:数据的持久化⽂件
HFile
中是按照
KeyValue
存储的,如果rowkey
过长,⽐如超过
100
字节,
1000w
⾏数据,光
rowkey
就要占⽤
100*1000w=10
亿个字节,将近
1G
数据, 这样会极⼤影响HFile
的存储效率;
MemStore
将缓存部分数据到内存,如果
rowkey
字段过长,内存的有效利⽤率就会降低,系统不能缓存更多的数据,这样会降低检索效率。⽬前操作系统都是64
位系统,内存
8
字节对齐,控制在
16
个字节,
8 字节的整数倍利⽤了操作系统的最佳特性;
3. 散列原则
:如果
rowkey
按照时间戳的⽅式递增,不要将时间放在⼆进制码的前⾯,建议将
rowkey
的⾼位作为散列字段,由程序随机⽣成,低位放时间字段,这样将提⾼数据均衡分布在每个RegionServer
,以实现负载均衡的⼏率。如果没有散列字段,⾸字段直接是时间信息,所有的数据都会集中在⼀个RegionServer
上,这样在数据检索的时候负载会集中在个别的RegionServer
上,造成热点问题,会降低查询效率;
4.
唯⼀
原则
:必须在设计上保证其唯⼀性,
rowkey是按照字典顺序排序存储的
,因此,设计
rowkey
的时候,要充分利⽤这个排序的特点,
将经常读取的数据存储到⼀块,将最近可能会被访问的数据放到⼀块
。
5.
Rowkey
设计结合业务
:在满⾜
rowkey
设计原则的基础上,往往需要将经常⽤于查询的字段正和岛
rowkey
上,以提⾼检索查询效率。
5.hbase.hregion.max.filesize应该设置多少合适
默认是256
,
HStoreFile
的最⼤值。如果任何⼀个
Column Family
(或者说
HStore
)的
HStoreFiles
的⼤⼩超过这个值,那么,其所属的HRegion
就会
Split
成两个。
众所周知hbase
中数据⼀开始会写⼊
memstore
,当
memstore
满
64MB
以后,会
flush
到
disk
上⽽成为
storefile
。当
storefile数量超过3
时,会启动
compaction
过程将它们合并为⼀个
storefile
。这个过程中会删除⼀些
timestamp
过期的数据,⽐如
update 的数据。⽽当合并后的storefile
⼤⼩⼤于
hfile
默认最⼤值时,会触发
split
动作,将它切分成两个
region
。
6.autoflush=false的影响
⽆论是官⽅还是很多blog
都提倡为了提⾼
hbase
的写⼊速度⽽在应⽤代码中设置
autoflush=false
,然后在在线应⽤中应该
谨慎进⾏该设置,原因如下:
(1)
autoflush=false
的原理是当客户端提交
delete
或
put
请求时,将该请求在客户端缓存,直到数据超过 2M(
hbase.client.write.buffer
决定
)
或⽤户执⾏了
hbase.flushcommits
()
时才向
regionserver
提交请求。因此即使htable.put
()
执⾏返回成功,也并⾮说明请求真的成功了。假如还没有达到该缓存⽽
client
崩溃,该部分数据将由于未发送到regionserver
⽽丢失。这对于零容忍的在线服务是不可接受的。
(2)
autoflush=true
虽然会让写⼊速度下降
2-3
倍,但是对于很多在线应⽤来说这都是必须打开的,也正是
hbase
为什么
让它默认值为
true
的原因。当该值为
true
时,每次请求都会发往
regionserver
,
⽽
regionserver
接收到请求后第⼀件事就
是写
hlog
,因此对
io
的要求是⾮常⾼的,为了提⾼
hbase
的写⼊速度,应该尽可能⾼地提⾼
io
吞吐量,⽐如增加磁盘、
使⽤
raid
卡、减少
replication
因⼦数等。
7对于传统关系型数据库中的⼀张table,在业务转换到hbase上建模时,从性能的⾓度应该 如何设置family和qualifier呢?
1、最极端的,①每⼀列都设置成⼀个
family
,②⼀个表仅有⼀个
family
,所有列都是其中的⼀个
qualifier
,那么有什么区别 呢?
1. 从读的⽅⾯考虑:
a.
family
越多,那么获取每⼀个
cell
数据的优势越明显,因为
io
和⽹络都减少了。如果只有⼀个
family
,那么每⼀
次读都会读取当前
rowkey
的所有数据,⽹络和
io
上会有⼀些损失。
b. 当然如果要获取的是固定的⼏列数据,那么把这⼏列写到⼀个
family
中⽐分别设置
family
要更好,因为只需⼀次
请求就能拿回所有数据。
2. 从写的⾓度考虑:
a.
内存⽅⾯来说,对于⼀个
Region
,会为每⼀个表的每⼀个
Family
分配⼀个
Store
,⽽每⼀个
Store
,都会分配⼀
个
MemStore
,所以更多的
family
会消耗更多的内存。
b.
从
flush
和
compaction
⽅⾯说,⽬前版本的
hbase
,在
flush
和
compaction
都是以
region
为单位的,也就是说当
⼀个
family
达到
flush
条件时,该
region
的所有
family
所属的
memstore
都会
flush
⼀次,即使
memstore
中只有很少的数
据也会触发
flush
⽽⽣成⼩⽂件。这样就增加了
compaction
发⽣的机率,⽽
compaction
也是以
region
为单位的,这样
就很容易发⽣
compaction
风暴从⽽降低系统的整体吞吐量。
c.
从
split
⽅⾯考虑,由于
hfile
是以
family
为单位的,因此对于多个
family
来说,数据被分散到了更多的
hfile
中,减
⼩了
split
发⽣的机率。这是把双刃剑。更少的
split
会导致该
region
的体积⽐较⼤,由于
balance
是以
region
的数⽬⽽不
是⼤⼩为单位来进⾏的,因此可能会导致
balance
失效。⽽从好的⽅⾯来说,更少的
split
会让系统提供更加稳定的在线
服务。⽽坏处我们可以通过在请求的低⾕时间进⾏⼈⼯的
split
和
balance
来避免掉。
2、因此对于写⽐较多的系统,如果是离线应该,我们尽量只⽤⼀个
family
好了,但如果是在线应⽤,那还是应该根据应⽤
的情况合理地分配
family
8.Hbase⾏健/列族的概念,物理模型,表的设计原则?
1. ⾏健:是
hbase
表⾃带的,每个⾏健对应⼀条数据。
2. 列族:是创建表时指定的,为列的集合,每个列族作为⼀个⽂件单独存储,存储的数据都是字节数组,其中的数据可以有很多,通过时间戳来区分。
3. 物理模型:整个
hbase
表会拆分为多个
region
,每个
region
记录着⾏健的起始点保存在不同的节点上,查询时就是对各个节点的并⾏查询,当region
很⼤时使⽤
.META
表存储各个
region
的起始点,
-ROOT
又可以存储
.META
的起始点。
4.
rowkey
的设计原则:各个列簇数据平衡,长度原则、相邻原则,创建表的时候设置表放⼊
regionserver
缓存中,避免⾃动增长和时间,使⽤字节数组代替string
,最⼤长度
64kb
,最好
16
字节以内,按天分表,两个字节散列,四个字节存储时分毫秒。
5. 列族的设计原则:尽可能少(按照列族进⾏存储,按照
region
进⾏读取,不必要的
io
操作),经常和不经常使⽤的两类数据放⼊不同列族中,列族名字尽可能短。
9.HBase存储单元Cell?(重点)
1. 单元
{row key
,
column
(
=<family>+<label>
),
version}
2. 唯⼀性;数据是没有类型的,以字节码形式存储
3. 表:
(
⾏
key
,列族
+
列名,版本
(
timestamp
))
->
值
10.说说HBase物理模型?(重点)
(
1
)
Table
中的所有⾏都按照
row-key
的字典序排列;
(
2
)
Table
在⾏的⽅向上分割为多个
Region
;
(
3
)
Region
按⼤⼩分割的,每个表开始只有⼀个
region
,随着数据增多,
region
不断增⼤,当增⼤到⼀个阈值的时
候,
region
就会等分成两个新的
region
,之后会有越来越多的
region
;
(
4
)
Region是HBase中分布式存储和负载均衡的最⼩单元
。不同
region
分布到不同的
regionserver
上;
(
5
)
region虽然是分布式存储的最⼩单元,但并不是存储的最⼩单元。
Region由⼀个或者多个store组成,每个store保存⼀个columns family;
每个store又由⼀个memstore和0⾄多个storeFile组成;
Memstore存储在内存中,storefile存储在HDFS上;
(6)
每个
column family
存储在
HDFS
上的⼀个单独⽂件中;
(7)
Key
和
version number
在每个
column family
中都保存⼀份;
(8)
空值不会被保存。
11.HBase的客户端Client?
1. 整个
HBase
集群的访问⼊⼜;
2. 使⽤
HBase RPC
机制与
HMaster
和
HRegionServer
进⾏通信;
3. 与
HMaster
通信进⾏管理类操作;
4. 与
HRegionServer
进⾏数据读写类操作;
5. 包含访问
HBase
接⼜,并维护
cache
来加快对
HBase
的访问。
12.介绍HBase⼆级索引?
1. HBase
提供了检索数据的功能,不过原有系统仅提供了通过
rowkey
检索数据的功能,过于单⼀,不灵活,⼀旦查询条改变了往往涉及到要全表扫描过滤,极⼤浪费机器物理资源,又达不到实时的⼀个效果。HBase
⼆级索引功能解决了原有HBase
系统中仅能够通过
rowkey
检索数据的问题,使得⽤户能够指定多种条件,在
HBase
表中进⾏数据的实时检索与统计。
2. HBase
只提供了⼀个基于字典排序的主键索引,在查询中只能通过⾏键查询或者扫描全表来获取数据。
3. HBase
基于
rowkey
的全局索引:
Zookeeper
的
znode
节点
/hbase/meta-region-server-->hbase:mata
13.每天百亿数据存⼊HBase,如何保证数据的存储正确和在规定的时间⾥全部录⼊完毕,不残留数据?
看到这个题⽬的时候我们要思考的是它在考查什么知识点?
我们来看看要求:
1
)百亿数据:证明数据量⾮常⼤
2
)存⼊
HBase
:证明是跟
HBase
的写⼊数据有关
3
)保证数据的正确:要设计正确的数据结构保证正确性
4
)在规定时间内完成:对存⼊速度是有要求的
那么针对以上的四个问题我们来⼀⼀分析
1
)数据量百亿条,什么概念呢?假设⼀整天
60x60x24 = 86400
秒都在写⼊数据,那么每秒的写⼊条数⾼达
100
万
条,
HBase
当然是⽀持不了每秒百万条数据的,所以这百亿条数据可能不是通过实时地写⼊,⽽是批量地导⼊。批量导⼊推荐使⽤BulkLoad
⽅式(
推荐阅读:
Spark
之读写
HBase
),性能是普通写⼊⽅式⼏倍以上
2
)存⼊
HBase
:普通写⼊是⽤
JavaAPI put
来实现,批量导⼊推荐使⽤
BulkLoad
3
)保证数据的正确:这⾥需要考虑
RowKey
的设计、预建分区和列族设计等问题
4
)在规定时间内完成也就是存⼊速度不能过慢,并且当然是越快越好,使⽤
BulkLoad
14.你知道哪些HBase优化⽅法(重点)
优化⼿段主要有以下四个⽅⾯
1)减少调整
减少调整这个如何理解呢?
HBase
中有⼏个内容会动态调整,如
region
(分区)、
HFile
,所以通过⼀些⽅法来减少这些会带来I/O
开销的调整。Region
如果没有预建分区的话,那么随着
region
中条数的增加,
region
会进⾏分裂,这将增加
I/O
开销,所以解决⽅法就是
根据你的RowKey设计来进⾏预建分区,减少region的动态分裂 HFile
。HFile是数据底层存储⽂件,在每个
memstore
进⾏刷新时会⽣成⼀个
HFile
,当
HFile
增加到⼀定程度时,会将属于⼀个region
的
HFile
进⾏合并,这个步骤会带来开销但不可避免,但是合并后
HFile
⼤⼩如果⼤于设定的值,那么HFile
会重新分裂。为了减少这样的⽆谓的
I/O
开销,建议估计项⽬数据量⼤⼩,给
HFile
设定⼀个合适的值
2)减少启停
数据库事务机制就是为了更好地实现批量写⼊,较少数据库的开启关闭带来的开销,那么
HBase
中也存在频繁开启关闭带来的问题。
关闭Compaction,在闲时进⾏⼿动Compaction
因为
HBase
中存在
Minor Compaction
和
Major Compaction
,也就是对
HFile
进⾏合并,所谓合并就是
I/O
读写,⼤量的HFile
进⾏肯定会带来
I/O
开销,甚⾄是
I/O
⻛暴,所以为了避免这种不受控制的意外发⽣,建议关闭⾃动 Compaction,在闲时进⾏
compaction
批量数据写⼊时采⽤BulkLoad
如果通过
HBase-Shell
或者
JavaAPI
的
put
来实现⼤量数据的写⼊,那么性能差是肯定并且还可能带来⼀些意
想不到的问题,所以当需要写⼊⼤量离线数据时建议使⽤
BulkLoad
3)减少数据量
虽然我们是在进⾏⼤数据开发,但是如果可以通过某些⽅式在保证数据准确性同时减少数据量,何乐⽽不为呢?
开启过滤,提⾼查询速度
开启
BloomFilter
,
BloomFilter
是列族级别的过滤,在⽣成⼀个
StoreFile
同时会⽣成⼀个
MetaBlock
,⽤于
查询时过滤数据
使⽤压缩
:⼀般推荐使⽤
Snappy
和
LZO
压缩
4)合理设计
在⼀张
HBase
表格中
RowKey
和
ColumnFamily
的设计是⾮常重要,好的设计能够提⾼性能和保证数据的准确性
RowKey设计
:应该具备以下⼏个属性
散列性:散列性能够保证相同相似的
rowkey
聚合,相异的
rowkey
分散,有利于查询
简短性:
rowkey
作为
key
的⼀部分存储在
HFile
中,如果为了可读性将
rowKey
设计得过⻓,那么将会增加存储
压⼒
唯⼀性:
rowKey
必须具备明显的区别性
业务性:举些例⼦
假如我的查询条件⽐较多,⽽且不是针对列的条件,那么
rowKey
的设计就应该⽀持多条件查询
如果我的查询要求是最近插⼊的数据优先,那么
rowKey
则可以采⽤叫上
Long.Max-
时间戳的⽅式,这样
rowKey
就是递减排列
列族的设计
列族的设计需要看应⽤场景
多列族设计的优劣
优势:
HBase
中数据时按列进⾏存储的,那么查询某⼀列族的某⼀列时就不需要全盘扫描,只需要扫
描某⼀列族,减少了读
I/O
;其实多列族设计对减少的作⽤不是很明显,适⽤于读多写少的场景
劣势:降低了写的
I/O
性能。原因如下:数据写到
store
以后是先缓存在
memstore
中,同⼀个
region
中存在多个列族则存在多个store
,每个
store
都⼀个
memstore
,当其实
memstore
进⾏
flush
时,属于同⼀个
region的store
中的
memstore
都会进⾏
flush
,增加
I/O
开销
15.HRegionServer宕机如何处理?
1
)
ZooKeeper
会监控
HRegionServer
的上下线情况,当
ZK
发现某个
HRegionServer
宕机之后会通知
HMaster
进⾏失效备援;
2
)该
HRegionServer
会停⽌对外提供服务,就是它所负责的
region
暂时停⽌对外提供服务
3
)
HMaster
会将该
HRegionServer
所负责的
region
转移到其他
HRegionServer
上,并且会对
HRegionServer
上存在memstore中还未持久化到磁盘中的数据进⾏恢复
4
)这个恢复的⼯作是由
WAL
重播来完成,这个过程如下:
wal
实际上就是⼀个⽂件,存在
/hbase/WAL/
对应
RegionServer
路径下
宕机发⽣时,读取该
RegionServer
所对应的路径下的
wal
⽂件,然后根据不同的
region
切分成不同的临时⽂件recover.edits
当
region
被分配到新的
RegionServer
中,
RegionServer
读取
region
时会进⾏是否存在
recover.edits
,如果有则进⾏恢复
16.HBase简单读写流程
读:
找到要读取数据的
region
所在的
RegionServer
,然后按照以下顺序进⾏读取:先去
BlockCache
读取,若
BlockCache
没有,则到
Memstore
读取,若
MemStore
中没有,则到
HFile
中读取。
写:
找到要写⼊数据的
region
所在的
RegionServer
,然后将数据先写到
WAL
中,然后再将数据写到
MemStore
等待刷新,
回复客户端写⼊完成。
17.HBase和Hive的对⽐(重点)
18.HBase与传统关系型数据库(如MySQL)的区别(重点)
1.
数据类型:
没有数据类型,都是字节数组
(有⼀个⼯具类
Bytes
,将
java
对象序列化为字节数组)。
2.
数据操作:
HBase
只有很简单的插⼊、查询、删除、清空等操作,表和表之间是分离的,
没有复杂的表和表之间的关系
,⽽传统数据库通常有各式各样的函数和连接操作。
3.
存储模式:
Hbase
适合于⾮结构化数据存储,
基于列存储⽽不是⾏
。
4.
数据维护:
HBase的更新操作
不应该叫更新,它
实际上是插⼊了新的数据
,⽽传统数据库是替换修改
5.
时间版本:
Hbase
数据写⼊
cell
时,还会附带时间戳,默认为数据写⼊时
RegionServer
的时间,但是也可以指定⼀个不同的时间。
数据可以有多个版本。
6.
可伸缩性,
Hbase
这类分布式数据库就是为了这个⽬的⽽开发出来的,所以
它能够轻松增加或减少硬件的数量
,并且对错误的兼容性⽐较⾼。⽽传统数据库通常需要增加中间层才能实现类似的功能。
19.什么时候适合使⽤HBase(应⽤场景)?(重点)
1.
半结构化或⾮结构化数据
:
2.
对于数据结构字段不够确定或杂乱⽆章⾮常难按⼀个概念去进⾏抽取的数据适合⽤
HBase
,因为
HBase
⽀持
动态添加列
。
3.
记录很稀疏:
4.
RDBMS
的⾏有多少列是固定的。为
null
的列浪费了存储空间。⽽如上⽂提到的,
HBase为null的Column不会被存储
,这样既节省了空间⼜提⾼了读性能。
5.
多版本号数据
:
6.
依据
Row key
和
Column key
定位到的
Value
能够有随意数量的版本号值,因此对于
须要存储变动历史记录的数据
,⽤HBase是很⽅便的。⽐⽅某个⽤户的
Address
变更,⽤户的
Address
变更记录也许也是具有研究意义的。
7.
仅要求最终⼀致性:
8.
对于数据存储事务的要求不像⾦融⾏业和财务系统这么⾼,只要保证最终⼀致性就⾏。(⽐如
HBase+elasticsearch时,可能出现数据不⼀致)
9.
⾼可⽤和海量数据以及很⼤的瞬间写⼊量:
10.
WAL
解决⾼可⽤,⽀持
PB
级数据,
put
性能⾼
11.
索引插⼊⽐查询操作更频繁的情况。⽐如,对于历史记录表和⽇志⽂件。(
HBase
的写操作更加⾼效)
12.
业务场景简单:
13.
不需要太多的关系型数据库特性,列⼊交叉列,交叉表,事务,连接等
。
其实,
Client
的元数据缓存不更新,当
.META.
的数据发⽣更新。⽐如因为
region
重新均衡,某个
Region
的位置发⽣了变化,Client
再次根据缓存去访问的时候,会出现错误,当出现异常达到最⼤重试次数后,
client
就会去
.META.
所在的RegionServer获取最新的
Region
信息,如果
.META.
所在
RegionServer
也变了,
Client
就会重新去
ZK
上获取
.META.
所在的RegionServer的最新地址。
21.请描述如何解决Hbase中region太⼩和region太⼤带来的冲突?
Region过⼤会发⽣多次compaction
,将数据读⼀遍并重写⼀遍到
hdfs
上,占⽤
io;
region过⼩会造成多次split
,region会下线,影响访问服务,调整
hbase.hregion.max.filesize
为
256m.
22.解释下 hbase 实时查询的原理(重点)
实时查询,可以认为是从内存中查询,⼀般响应时间在
1
秒内。
HBase
的机制是数据先写⼊到内存中,当数据量达到⼀定的量(如 128M
),再写⼊磁盘中, 在内存中,是不进⾏数据的更新或合并操作的,只增加数据,这使得⽤户的写操作只要进⼊内存中就可以⽴即返回,保证了 HBase I/O
的⾼性能。
23.HBase 宕机如何处理?
宕机分为
HMaster
宕机和
HRegisoner
宕机。
a.
如果是
HRegisoner
宕机,
HMaster
会将其所管理的
region
重新分布到其他活动的
RegionServer
上,由于数
据和⽇志都持久在
HDFS
中,该操作不会导致数据丢失。所以数据的⼀致性和安全性是有保障的。
b.
如果是
HMaster
宕机,
HMaster
没有单点问题,
HBase
中可以启动多个
HMaster
,通过
Zookeeper
的Master Election 机制保证总有⼀个
Master
运⾏。即
ZooKeeper
会保证总会有⼀个
HMaster
在对外提供服务。
所有评论(0)