构建Put对象
设计合理的RowKey
表中所有数据都是基于RowKey排序的,RowKey的设计对读写效率有着直接的性能影响。
避免“热点数据”的方法有以下几种:
- reversing :倒置,有时可以保证先导字段的数据均匀,但是对读取来说有时是不有好的。
- salt:和上者一样
- hash:将rowkey通过一个hash函数计算,有利于写,但是对于范围scan和模糊查询,性能堪忧。
定义列
每个列体现为一个KV,同时还需要定义column和qualifier。
数据路由
meta Region的路由信息存放于zookeeper中,初次读取meta Region,需要与zookeeper建立session。然后读取meta Region所在的Region server,再从meta Region中读取rowkey所关联的Region信息。
HBase client有cache机制来缓存Region route信息,避免每次都需要访问meta Region和zookeeper。
客户端侧的数据分组打包
- single put:比较简单,先定位rowkey对应的Region和Region Server ,client直接发送请求。
- batch put:首先按照Region分组,遍历rowkey,确定与之对应的Region。然后,按照Region Server分类打包,封装为MultiAction对象,一并发送。
安全访问控制
Kerberos确保一个用户的和合法性,ACL确定该用户的权限范围。
READ、WRITE、EXEC、CREATE、ADMIN
库->namespace->表->列族->列
Region Server分发
- single put: 直接将request 转发给相应Region。
- batch put:每个写入request被包装为一个RegionAction对象,遍历Region Action,串行执行。所以不是batch越大越好。
Region 内部处理:写入WAL
LSM-Tree架构,顺序读写速度远高于随机读写速度。
每一个Region中随机写入的数据,都先缓存在内存中(MemStore),这些数据顺序写入到WAL中(Write-Ahead-Log)的日志文件中(按时间顺序),可以防止未持久化而断电等情况。
WAL进阶
当正在写入的WAL达到一定大小,会创建新的WAL,若WAL所关联的Region中数据都已经持久化,则此WAL暂时给归档到另外一个目录。
若对HBase中的数据可靠性要求不高,则允许跳过写WAL步骤。
Region内部处理:写MemStore
每一个column family 在Region内被抽象为HStore,每个HStore拥有一个MemStore。
MemStore中存放KV的结构,被称为CellSet,CellSet的核心是ConcurrentSkipListMap(跳表)
打两个的随即写会产生大量的Java对象,GC压力比较大。优化方式:内存分页。