一.表设计
1.预分区【Pre-Creating Regions】
默认情况下,在创建HBase表的时候会自动创建一个region分区,当写入数据时,所有的HBase客户端都向这一个region写数据,直到这个region足够大时才进行切分。因此,为了提高批量写入的效率可以预先创建好多个分区【这个要和rowkey的设计紧密关联】,这样当数据写入HBase时会按照region分区的情况,不同rowkey类型的数据写入对应的分区中,写入数据的速度会大大提高,同时也做到了数据的负载均衡。
2.Row Key【行键】
HBase中的rowkey用来检索表中的记录,支持一下三种方式:
1.通过单个rowkey访问,即按照某个rowkey键值进行get操作。
2.通过rowkey的range进行scan,即通过设置startRowKey和endRowKey在这个范围内进行扫描。
3.全表扫描,及直接扫描整张表中所有行记录。
备注:
1.在HBase中rowkey可以是任意字符串,最大长度64KB,实际应用中一般为10~100bytes,存为byte[]字节数组,一般设计成定长的。
2.rowkey是按照字典顺序存储,因此,可以在设计rowkey时充分利用这一点,将经常一起读取的数据存储到一块,将最近可能被访问的数据放在一块。
3.Column Family【列簇】
不要在一张表里定义太多的column family。目前HBase并不能很好的处理超过2~3个column family的表。因为某个column family在flush的时候,它邻近的column family因关联效应被触发flush,最终导致系统产生更多的I/O。
4.In Memory
创建表时,可以通过HColumnDescriptor.setInMemory(true)将表放到RegionServer缓存中,保证在读取的时候被cache命中。
5.Max Version
创建表时,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)设置数据的最大最大版本。
6.Time To Live
创建表时,可以通过HColumnDescriptor.setTimeToLive(int timeToLive)设置表中数据的生命周期,过期数据将自动被删除,例如如果只需要存储最近一天的数据,那么可以设置为HColumnDescriptor.setTimeToLive(1 * 24 * 60 * 60)。
7.Compact & Split
在HBase中,数据在更新时首先写入WAL(HLog)和内存(MemStore)中,MemStore数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemSotee,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。与此同时系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了(minor compact)。
StoreFile是只读的,一旦创建后就不能再修改,因此HBase的更新其实是不断追加的过程,若一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(major compact),将对同一个Key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值时又会对StoreFile进行切分(split),等分成两个SotreFile。
由于对表的更新是不断追加的,处理读请求时,需要访问Store中全部的StoreFile和MemStore,将它们按照row key进行合并,由于StoreFile和MemSrore都是进行过排序的,并且StoreFile带有内存索引,通常合并过程是比较快的。
实际应用中,可以考虑必要时手动进行major compact,将同一个row key的修改进行合并形成一个大的StoreFile。同时可以将SoreFile设置大些,减少split的发生。