hbase相关操作
- row key
按字典序排(方便区间查找)
rowkey只能存64k的字节数据(10-100个字节,越短越好)
列族是最小的控制单元,权限,存储,调优都是针对于列族
zookeeper里保存着表名
元数据表在Hregionserver中,
0.92 有root目录与meta目录,
从0.98开始只有meta目录没有root目录
client去zookeeper中获取元数据表所在的Hregionserver位置,之后从元数据表中获取所查表的Hregionserver地址,最后去对应的Hregionserver中读写数据
memstore满64M进行溢写持久化
hlog中的日志是写到内存中的,由后台进程logsync默认1s进行刷新一次写入到磁盘
memstore是写缓存,但也提供了一部分读缓存的功能
blockcatch是读缓存
数据读取时,会先去memstore中去读取数据,然后去blockcache中读取数据,最后去hfile中读取数据,从hfile中读到的数据会被再次缓存到blockcache中,因为blockcache也有大小限制,所以要进行数据淘汰,默认采用RLU最近最少读取的数据进行淘汰
blockcache的大小默认为4G,最大可以为hbase集群max.heap.size最大内存的38%,建议不要超过32G
client端也会缓存部分的数据
- zookeeper作用
保证只有一个master
存所有的region的寻址入口
实时监控region server的上线下线信息并通知Hmaster
存Hbase的schema和table元数据
- Hmaster作用
为Hregionserver分配region
负责Hregionserver的负载均衡
发现失效region server并重新分配其上的region(数据不会移动,数据是在hdfs上,只是将这些region的寻址入口进行了移动)
管理cud操作
- regionserver作用
维护region,处理对应的io
切分运行过程中变得过大的region
- 组件
一个Hstore对应一个列族,一个Hstore包含一个memstore,当达到阀值时生成一个新文件storefile,一个hstore中包含多个storefile,当一个hregion中的多个hstore的大小与数量达到阀值时,会进行split,将region切割,并分发到不同的hregionserver中,实现负载均衡
写Hlog时默认过期时间是2d,会被移入oldwal目录中
默认超过256M不再参与任何合并
- hbase中的数据文件以sequece格式存储,无法直接查看,可以通过命令
hbase hfile -p -f file:///home/xxx/xxx/data/default/xxx/xxx 查看
表名所在的外层文件夹为regionId
- rowkey设计原则
1、超短越好,提高效率:每条数据都要存储一个rowkey,其所占的空间是巨大的,其二,过大的rowkey会影响hbase的缓存,使用其有效利用率降低,无法缓存更多数据,降低检索效率
2、 散列原则:实现regionserver负载均衡,避免热点问题,但会导致无法连续读
具体做法有:
加盐:添加随机值
hash: 采用md5散列取前4位做前缀
反转:将手机号反转
3、唯一原则:
列族设计原则:
1、最好小于3个,原因如下:
每个cf对应一个memstore,但是memstore的flush操作是region级别的,会连带将 其它列族的memstore也进行flush,从而导致太多小文件
当region太大进行split时,如果多个cf的数据量相差悬殊,会对本就小的文件进一步拆分
hbase的compaction也是region级别的,所以过多的列族会导致不必要的io
hdfs下一个目录的文件数量是有限制的(dfs.namenode.fs-limits.max-directory-items),如果有x个region,每个region有y个cf,每个cf对应z个hfile,则可能xyz会大于hdfs的配置值
- hbase缓存过期机制
有3个队列:
single:类型jvm中的青年代,
multi :类型jvm中的老年代
,in memory:类似jvm中的持久化区,hbase的元数据,如meta表数据等会放置在这里
- max version不要设置太大,会占用更多空间
- TTL 可以设置数据过期时间
ColumnFamilyDescriptorBuilder.setTimeToLive(xxx秒)
select时也会过滤掉
- minor合并的判断流程较复杂
有最小3与最大10的文件数量限制,有最小(一定要)与最大(一定不要)的文件大小判断,其余的文件要按文件的存在时间排序并搭配compaction.ratio进行判断是否加入合并。
- major合并
major的自动合并(默认每24h进行一次触发,jetter默认为0.2对时间进行上下浮动形成一个时间范围,以防止所有的regionserver在一个时间点同时进行major合并)应当关闭,通过脚本进行手动触发
- 如果数据可以允许丢失,可以选择关闭WAL,或是将WAL写入改为异步,默认写缓存与写入WAL为同步写入
- 在使用put操作时,尽量使用批量写入,以减少client端与regionserver端之间的rpc连接数,但是批量写入要么全部成功,要么全部失败。
- 可以在业务允许的情况下开启异步批量提交
提交分为两个阶段,先提交到client端的缓存(默认2M)中,当达到阈值时,再提交到regionserver,但会存在数据丢失的可能性
使用setAutoFlush(false)进行设置
- 保证region的个数大于或等于regionserver个数量,保证所有的节点都可以被充分利用
- 一般业务都是采用多节点批量提交的方式,但如果个别 节点无法及时响应会导致整个的批量请求超时,(不怕节点宕机,就怕节点奄奄一息),所以我们要通过rowkey的设计及预分区策略来保证请求写入均衡,避免热点
- 写入的keyvalue是否太大
- 可以将WAL硬件改为SSD
- 当前所有的region在regionsever上共享一个wal文件,会存在数据竞争,可以将wal改为每个namespace共享,提升20~40%性能
- scan操作默认是会进行缓存到本地客户端中,每次100条数据,但是大数据量情况下可以通过setCaching()方法来将数值调高至500或1000,以减少rpc次数
- hbase也提供了批量get接口,类似于批量put优化原理,推荐使用批量操作
- 请求时尽量指定出具体的过滤条件,而不是在查询后再过滤,以避免不必要的文件扫描与文件io
- 进行离线批量读取文件时,请设置禁用缓存,避免将缓存中的热点数据挤出,scan.setBlockCache(false)
- blockcache设置是否合理
默认情况下blockcache与memstore各占40%,可以根据业务进行调整,比如读多写少的业务可以将blockcache占比调大,另外blockcache的策略选择也很重要,不同的策略对读性能影响不大,但对GC的影响却很大,尤其是bucketcache的offheap模式下GC表现很好,另,Hbase2.0有对offheap进行过改造,使其读性能提升2~4倍。
注意观察所有regionserver的缓存未命中率,GC日志,以确认blockcache是否可优化
建议内存配置量<20G,blockcache策略选择LRUBlockcache,否则选择BucketCache策略的offheap模式
hfile文件是否过多,通过设定hbase.hstore.compaction.min=3(避免太大),与hbase.hstore.compaction.max.size(避免太小)=RegionSize/hbase.hstore.compaction.min来进行调整
- compaction是否消耗系统资源太多:minor(太频繁)与major(阀值太大导致直接进行了major,没有进行minor)设置不合理
- 数据本地率是否太低:
数据本地率太低会造成大量的跨节点网络io,数据本地率低一般是因为region的迁移(自动balance开启,regionserver宕机迁移,手动迁移等),因此一方面可以通过region无故迁移来保持数据的本地率,另一方面如果本地率较低,可以通过执行major_compact来提升数据本地率到100%
建议:避免region的无故迁移,比如关闭自动balance,rs宕机及时拉起并迁回飘走的region等,在业务的低峰期进行majar_compact