hbase面试

1:hbase架构

Client 包含了访问 HBase 的接口,另外 Client 还维护了对应的 Cache 来加速 HBase 的访问,比如 Cache 的.META.元数据的信息。

HMaster:

  • HBase 的主节点,负责整个集群的状态感知、Region server的负载均衡、region分配,管理用户对
  • table的增删改操作。
  • HMaster 负载压力相对于 HDFS 的 NameNode会小很多。HBase 的 HMaster 其实就算是宕机一段时间也可以正常对外提供服务的

RegionServer

  • HBase 中真正负责管理 Region 的服务器,也就是负责为客户端进行表数据读写的服务器,
  • 负责Region的拆分以及hfile的合并
  • 负责和底层的HDFS的存储交互,每一台 RegionServer 会管理很多的 Region

ZooKeeper

  • 保证任何时候集群中只有一个master,也就是master管理选举,避免单点故障
  • 实时监控Region server的上线和下线信息。并实时通知Master
  • 存储HBase的schema和table元数据,即表的region以及对应的region server服务器
  • 存贮所有Region对应的region server的寻址入口。

HDFS 用来存储 HBase的数据

2:hbase读写流程以及性能优化
1:写入流程

1:提交put请求后,HBase客户端会将put请求添加到写入缓冲区中(默认hbase.client.write.buffer = 2M),符合一定条件就会通过AsyncProcess异步批量提交。
2:Client提交写请求之前,访问zookeeper 会在元数据表.meta.中根据rowkey找到它们归属的region server,获取对应的region
3:获取Region更新共享锁行锁: HBase中使用行锁保证对同一行数据的更新都是互斥操作,用以保证更新的原子性,要么更新成功,要么失败。
4:追加到HLog:HBase使用WAL预写日志机制保证数据可靠性,即首先写日志再写缓存
4:写缓存memstore:HBase中每列族都会对应一个store,用来存储该列数据。每个store都会有个写缓存memstore,用于缓存写入数据。HBase并不会直接将数据落盘,而是先写入缓存,等缓存满足一定大小之后再一起落盘。
6:释放行锁以及共享锁,提升性能,汇报client写入完成。
7:HLog真正异步提交写到HDFS,在释放行锁之后执行sync操作是为了尽量减少持锁时间,提升写性能。如果Sync失败,执行回滚操作将memstore中已经写入的数据移除。
8:flush memstore:满足flush条件会启动flush线程将数据刷新到硬盘形成storefile(Hfile),将内存中的数据删除,同时删除HLog中的历史数据
flush条件

  • 1、 全局内存控制:当所有 memstore 占整个 heap 的最大比例的时候,会触发刷盘的操作。
    这个参数是hbase.regionserver.global.memstore.upperLimit,默认为整个heap内存的40%。
    参数是控制内存整体的使用情况,但这并不意味着全局内存触发的刷盘操作会 将 所 有 的 MemStore 都 进 行 输 盘 , 而 是 通 过 另 外 一 个 参 数
    hbase.regionserver.global.memstore.lowerLimit 来控制,默认是整个 heap 内存的 35%。当
    flush 到所有 memstore 占整个 heap 内存的比率为 35%的时候,就停止刷盘。这么做主要是为了减少刷盘对业务带来的影响,实现平滑系统负载的目的。
  • 2、 当 MemStore 的大小达到 hbase.hregion.memstore.flush.size 大小的时候会触发刷盘,默
    认 128M 大小也就是hdfs文件块大小
  • 3、 前面说到 HLog 为了保证 HBase 数据的一致性,那么如果 HLog 太多的话,会导致故障恢
    复的时间太长,因此 HBase 会对 HLog 的最大个数做限制。当达到 Hlog 的最大个数的时
    候,会强制刷盘。这个参数是 hase.regionserver.max.logs,默认是 32 个。
  • 4、 可以通过 HBase Shell 或者 Java API 手工触发 flush 的操作
  • 5 、 当有任何一个 MemStore 的存活时间超过了 1h, 则这个 RegionServer 中所有的 MemStore 一起刷到 HFile 中.
    由于前面的刷写过程的存在, 有可能会导致磁盘上有比较多的 HFile 小文件, 而 HDFS 并不适合存储小文件, 所以就存在了一个小文件合并的过程

9:合并阶段:有 2 种合并

  • Minor_compact小合并:当一个store(列簇)里面允许存在的HFile的个数,超过这个个数会被写到一个新的HFile里面,也就是每个region的每个列族对应多个memstore在flush为HFile的时候,默认情况下当超过3个HFile的时候就会对这些文件进行合并重写为一个新文件,设置个数越大越减少触发合并的时间,但是每次合并的时间就会越长
  • major_compact大合并:指一个 region 下的所有 HFile 做归并排序, 重写所有的Hfile写成一个hfile, 占用大量硬盘IO和网络带, 这可以提高读性能。
    但是大合并后过大的hfile会触发region分裂

10:region分裂:
当region达到10G大小时会触发splient分裂,此时它就分裂成 2 个子region。分裂时会阻塞读写会影响读写性能,所以一般会关闭自动分裂,而在低谷时段手动去进行避免影响系统。
2个子 region, 各占原始 region 的一半数据, 仍然被相同的 region server管理.
如果出现负载均衡,master会触发region迁移,发送到其他的region server

2:读取流程

1)Client先访问zookeeper,从meta表所处位置regionserver(ip),

2)访问meta表,然后读取meta表中的数据。meta中又存储了用户表的region信息;

3)根据namespace、表名和rowkey在meta表中找到对应的region信息;

4)找到这个region对应的regionserver;

5)查找对应的region;

6)先从MemStore找数据,如果没有,再到BlockCache里面读;

7)BlockCache还没有,再到StoreFile上读(为了读取的效率);

8)如果是从StoreFile里面读取的数据,不是直接返回给客户端,而是先写入BlockCache,再返回给客户端。

3:读写优化

1:写入优化

  • 1:表创建:预创建region
    默认情况下,HBase中的表最初是使用一个region创建的。这意味着所有客户端都将写入同一region,直到该region足够大再拆分并分布完毕才接受写入,加快批量导入过程的一种有用模式是预先创建空白region。个数根据数据量预计,因为太多region实际上会降低性能。
    api有两种方式
    admin.createTable(table, startKey, endKey, numberOfRegions);
    admin.createTable(table, splits);

  • 2:性能优化
    1:禁用WAL预写日志功能会提升性能,但是会在服务器崩溃导致数据丢失,
    2:延迟WAL日志刷新,未刷新时服务器奔溃可能丢失数据
    3:是否多次写入较大数据查看日志中"vlen":即写入数据大小

参数调优

hbase.hregion.memstore.block.multiplier=8
hbase.hregion.memstore.flush.size=268435456
hbase.hstore.blockingWaitTime=60000
hbase.regionserver.thread.compaction.large=10

2:读取优化

性能优化

  • 1:使用布隆过滤器:hbase的storefile有很多,随机查的时候可能需要遍历很多storefile,如果指定了bloomfilter,则在get查询(scan不管用)的时候就可以过滤掉很多不符合规则的storefile,提高查询效率
  • 2:在显式选择了列时scan.addColumn,HBase将安排搜索操作以在所选列之间进行搜索,版本过多比较慢,可以使用scan.setAttribute(Scan.HINT_LOOKAHEAD, Bytes.toBytes(2));
    scan.addColumn(…);
    scan.setAttribute(Scan.HINT_LOOKAHEAD, Bytes.toBytes(2));
    table.getScanner(scan);
  • 3:忘记关闭ResultScanner会导致性能问题,可以放在try / catch块关闭
  • 4:启用块缓存,但是会占用堆外内存,综合考虑
3:regionserver宕机的影响

1.zookeeper发现并确认RS宕机, 在RS列表中删除宕机的节点,

2.该 HRegionServer 会停止对外提供服务,就是它所负责的 region 暂时停止对外提供服务;

3.master将该服务器上的Region分配给其他活着的Region Server,保证region完整性

4.Region Server将Hlog持久化到HFile中,同时把memostore中数据刷写到磁盘,避免数据写入丢失

4. HBase 的 rowKey 的设计原则?
  • ① Rowkey 长度原则
    Rowkey 是一个二进制码流,建议是越短越好,不要超过 16 个字节。
    原因如下:
    (1)数据的持久化文件 HFile 中是按照 KeyValue 存储的,如果 Rowkey 过长比如 100个字节,1000 万列数据光 Rowkey 就要占用 100*1000 万=10 亿个字节,将近 1G 数据,这会极大影响 HFile 的存储效率;
    (2)MemStore 将缓存部分数据到内存,如果 Rowkey 字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此 Rowkey 的字节长度越短越好。
    (3)目前操作系统是都是 64 位系统,内存 8 字节对齐。控制在 16 个字节,8 字节
    的整数倍利用操作系统的最佳特性。

  • ② Rowkey 散列原则:避免数据热点问题,导致读写缓慢

  • ③ Rowkey 唯一原则:必须在设计上保证其唯一性,避免数据丢失

5:列式存储和行式存储的区别
  • 行式存储:传统关系型数据库使用的存储结构就是行式存储结构,记录以行的形式存储在数据库关系表中。在分布式系统存储下,表按照行水平分割,每行中所有数据存放在同一个数据块中,数据块又有可能分布在不同的节点上,如果读取行中的一列和二列则需要先读取本地节点上所有符合条件的行,然后过滤出一列和二列。行式存储结构的优点是数据加载速度快,所有数据优先从本地读取,不需要额外的网络开销。缺点是每行中所有列都放在了相同的数据块中,在读取一行数据时会读取当前行的所有列,这样就增加了额外的磁盘I/O开销。并且每一列存储的数据类型不都一样,在数据压缩时不同数据类型压缩效果会很大,这样会导致磁盘利用率低,同样也会导致磁盘I/O加大。
  • 列式存储:列式存储结构将关系表按列垂直分割成多个子关系表,分割后的每组子关系表中的所有数据存放在同一个数据块中,每一列都是独立存储的。列式存储结构的优点是只读取有用的列,能够避免额外的磁盘I/O开销,同一列中的数据类型相同,因此数据压缩时有很好的压缩比,提高了磁盘的空间利用率。缺点是由于列式存储按照列来垂直分割数据,因此不同的列可能分布在不同的节点上,读取不同的列会出现跨界点访问的问题,这样就增加了网络传输所消耗的时间。

1.存储数据结构方面:行式存储倾向于结构固定,列式存储倾向于结构弱化,所以多存储本结构化数据和非结构化数据,对于空列可以不存储,减小存储空间利用(按量自取)。
2.读写性能方面:行存储列存储的写入性能由写入者一次完成保证了数据完整性,性能更高,列存储写入次数明显多于行存储。读取数据时列存储只读取相关列,减少冗余数据,降低网络io,所以
3.使用场景:列存储多用在OLAP( 数据在线分析处理),因为查询需要访问数百万到数十亿的数据行,并且通常只对少数数据列感兴趣。行式存储因为事务的特性多用在OLTP(联机事务处理,如银行交易,订票系统)中,处理事务性数据进行增删改查
4.行式存储一行数据只需一份主键,列式存储一行数据需要多份主键,列式存储除了数据外,还要存储列名。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值