namenode时,会导致datanode的id不相同无法启动。解决办法是将name的classid复制到/hadoop/hdfs/data/current/VERSION里面的clusterID=CID-809a0ce3-839d-42ba-9171-a955ae276820
hbase:meta
Hbase:meta(以前叫做meta),主要储存系统中的region信息,而他却被zookeepr维护。
HbaseMate表结构
Key:
如若获取rowkey对应的server则get操作时只能命中一个值。
(rowkey格式([table],[region start key],[region id]),regoin具有唯一性)
Values:
info:regioninfo(序列化的Hregioninfo实例)
HregionInfo:
一个region信息有一下内容组成:
Tablename,Startkey,regionid,replicaid,encodedName,endkey,split//该region是否被split
offline//该region是否离线,Server//该region的端口,Serverstartcode//包含该region的regionServer进程的启动时间
HMaster(主节点):
Hmaster允许多个Hmaster节点共存,但是这需要Zookeeper的协助。不过当多个Hmaster节点共存时,只有一个Hmaster是提供服务的,其它的Hmaster节点处于待命的状态。当正在工作的Hmaster节点宕机时,其它的Hmaster则会接管Hbase集群。
①负责给Regionserver分配region,协调各个regionServer(在启动时分配region,在恢复或是负载时重新分配region),当某一个regionserver故障后会分配其所在的region到新的regionserver上
②对外提供接口:控制台,rpc服务(监控集群中的Regionserver的工作状态,通过监听zookeepr对于ephemeral node状态的通知),web页面(http://hadoop01:16010/master-status).
③提供处理创建,更新,删除,查找等schema操作,(DDL操作),控制权限(ACL),当加载协处理器即observer(RegionObserver:提供二级索引,WALObserver:提供WAL相关操作钩子,MasterObserver:提供DDL类型的操作钩子,如创建,删除,修改数据),和endpoint时会告知其他节点运行下线
④Mate相关的存储预写日志的清理,清除已经被刷到memstore中的数据.(优化点:①在客户是很重视安全性能的前提下关掉HLog预写日志时插入数据会更快。②当HLog挂载到固态硬盘会更快)
HRegionServer(从节点):
①负责对region的管理与服务,一般一个Datanode放一个Regioser。
②读写HDFS,管理table中的数据
③Clint直接通过Regionserver读写数据(从Zookeepr中获取 到元数据找到Rowkey所对应的Regionserver后)
④负责Region相关的io操作
⑤对过大的Region的进行切割,并定期检查小合并。
Region
Region是hbase中分布式存储和负载均衡的最小单位,但不是最小的存储单元。如个一个表格很大,并由多个CF组成时,那个表的数据将存放在多个region中,并且每个region会关联多个存储单元store。表在行方向分割为多个region,region是按大小分割的,随着region不断增大,当增大到一个阀值的时候,region就会分成两个region。
Store
每个region中包含了多个store对象,一个store包含一个memstore和若干个storefile,storefile中包含一个或多个hfile。Memstore存放在内存中,storefile存放在hdfs上。
Hfile
Hfile由很多个数据块(block)组成,并且有一个固定的结尾块。其中的数据块是由一个header和多个key-value的键值对组成。在结尾块中包含了数据相关的索引信息,系统也是通过结尾块的索引信息找到hfile中的数据。
问:什么是大合并?
删除一条记录,就会在该记录上打上标记,被打上标记的记录就成了墓碑记录,该记录使用get和scan查询不到,但还是在HFile中。只有进行大合并的时候才会删除HFile中的墓碑记录。大合并:指定region的一个列族的所有HFile.合并完成后,这个列族的所有HFile文件合并成一个HFile文件,可以在shell中手动触发,但该动作相当耗资源。小合并是将多个小的HFile文件内容读取出来合并生成一个大的HFile,把新文件设置成激活状态,然后删除小的HFile
问:为什么大合并会占用相当多的资源,数据大合并期间都在做什么?
因为Hbase上被标记过期和删除的标签需要清理 如果表相当大亿量级别时,则占用时间很长,此时该表所有的region下线,不能进行查询服务,因为占用了大量资源导致执行其他的服务时性能底下,一般大合并时间选在夜间凌晨三点左右 用户不在使用资源时,服务器很闲的时候。
问:HBase性能在什么时候性能最佳?
在大合并刚结束一段期间内,因为所有的小Hfile合并为大Hfile文件。
一个Regionserver中有一个WAL文件。
每个region有一个blockcache。
每个列簇都有自己的memstore(基于内存)
Regionserver(WAL)->region(BlockCache)->column family(memstore)
Hbase写流程:
Client先访问zookeeper,从.META.表获取相应region信息,然后从meta表获取相应region信息根据namespace、表名和rowkey、meta表的数据找到对应的region信息再找到对应的regionserver这时Hbase会同时进行俩个动作,把记录写在WAL(write ahead log)日志文件中,每台服务器所有表共享都共享一个WAL文件,然后会写到memstore内存中,memstore是内存中的写入缓冲区,如果memstore写满就刷新写到硬盘中,生成HFile文件。当服务器宕机时memstore内存中的内容就没了,这时可以通过回放WAL日志文件恢复,回访的动作有hbase内部机制调用,不需要用户调用。
HFile存储在底层文件系统,hbase是hadoop数据库,所以会在分布式文件系统hdfs上,HFile对应列族,一个列族可以有多个HFile文件,一个HFile文件是一个列簇中的内容。在集群的每个节点上,每个列簇有一个memStore.注意千万别把WAL关闭
Hbase读流程:
hbase读路径顺序:>memstore>blockCache==>Hfile
Client先访问zookeeper,从.META.表获取相应region信息,然后从meta表获取相应region信息根据namespace、表名和rowkey、meta表的数据找到对应的region信息再找到对应的regionserver然后在memstore上找数据,找不到就到blockCache,再找不到就读取HFile文件到内存中,Hbase使用blockCache缓存技术,blockCache保存从HFile中读取到内存的频繁访问的数据,每个列簇都有自己的blockCache (block是建立索引的最小数据单元,block大小是可以调整的,默认是64kb)一个完整的行信息可能存放在多个HFile中,为了读出完整行,Hbase可能需要读取包含该行信息的所有HFile。
Region为啥要split?
HBase中的表格可以根据行键水平分割为一个或几个region。每个region中包含了一段处于某一起始键值和终止键值之间的连续的行键。
每一个region的默认大小为1GB。
相应的Region server负责向客户提供访问某一region中的数据的服务。
每一个Region server能够管理大约1000个region(这些region可能来自同一个表格,也可能来自不同的表格)。
每一个表格最初都对应于一个region。随着region中数据量的增加,region会被分割成两个子region。每一个子region中存储原来一半的数据。同时Region server会通知HMaster这一分割。出于负载均衡的原因,HMaster可能会将新产生的region分配给其他的Region server管理(这也就导致了Region server服务远端数据的情况的产生)。
Region Split过程如何进行的?
从逻辑上讲,region split的过程很简单。我们在该region的keyspace中找到一个合适的split point,在这个split point上将该region的数据划分为两个新的region。然而,这个过程的细节并不简单。当split发生时,新创建的子region不会立即将所有数据重新写入新文件。相反,它们创建类似于符号链接文件的小文件,命名为引用文件(reference files),根据split point,指向父存储文件的顶部或底部。引用文件就像常规的数据文件一样,但是只有一半的记录被考虑。如果没有对parent region的不可变数据文件的引用,则该区域只能被分割。这些参考文件会逐渐被compact,从而使该区域不再引用它的父文件,并且可以进一步分割。
尽管split该region是由regionserver做出的本地决策,但split过程本身必须与许多参与者协调。regionserver在split之前和之后通知Master以更新元数据表(hbase:meta表)。这样,客户端就可以发现新的子region,并在HDFS中重新安排目录结构和数据文件。region split是一个多任务的过程。为了在出现错误的情况下启用回滚,所以split是事务性操作,regionserver在内存中保留了执行过程日志。regionserver执行split的步骤在RegionServer Split Process中得到了说明,执行顺序见下图中的标签。regionserver或hmaster的操作显示为红色,而来自客户端的操作则显示为绿色。
1.HRegionServer在本地决定split 该region,并准备split。分割事务开始了。作为第一步,HRegionServer获取表上的共享读锁,以防止在split过程中对模式进行修改。然后在/hbase/region-in-transition/region-name中创建一个znode,并将znode的状态设置为splitting。
2.HMaster读取这个znode,因为它读取原region-in-transition的znode。
3.HRegionServer在parent’s region的HDFS目录下创建一个名为.splits的子目录.
4.HRegionServer 将被split的parent Region 关闭并在本地数据结构(local data structures)中标记为offline。因此正在splitting的region 当下就是offline状态。这个时候对该parent Region的客户端读写请求就会抛出“NotServingRegionException”的异常,客户端会进行一些retry,直到region被flush。(The client will retry with some backoff. The closing region is flushed.)
5.HRegionServer 在.splits目录下为子region创建目录,并创建必要的数据结构。然后,它会分割store files,因为会在parent region的每个store file上创建两个referrence file,这些referrence file会指向parent region’s files。
6.HRegionServer 在HDFS中为两个子region的referrence file创建实际的region目录。
7.HRegionServer会向hbase:meta表发送一个put请求,将parent region 标记为offline,并向hbase:meta表中添加子region的信息。这个时候子region在hbase:meta表中并没有单独的条目,如果扫描hbase:meta表,会发现parent region正在split,并不能看到子region的信息(需要等待之前的操作完成)。当子region 的信息写入hbase:meta表完成以后,表明这个parent region 被有效的split。如果RegionServer执行这个过程失败,master和下一个使用这个region的regionserver会清除split相关的状态数据。meta表更新后,由master推进这个split过程。
8.regionserver 并行启动两个子region.
9.regionserver将两个子region的相关信息写入meta表,这时候两个子region状态即为online。在这之后客户端就可以发现这两个新的region 并可以向他们发起请求。客户端会将meta表数据缓存到本地,但是当他们向regionserver或者meta表发起请求时,他们的本地缓存将会失效,这时他们会从meta表重新读取新的region信息。
10.regionserver将zookeeper中的znode /hbase/region-in-transition/region-name状态更新为split,这样master就可以获取到该信息。如果需要的话,balancer可以自由的将子region负载均衡到需要的regionserver上。整个split事务就这样完成了。
11.split完成后,meta表和HDFS都还保留了parent region的引用,这些引用会在子region进行compaction操作重新数据时删除。master的GC任务会周期性的检查子region是否还指向parent region 的存储文件,如果没有,则parent region 被删除。
Zookeepr
①MasterElection 机制保证且允许总有一个Master在运行
②实时监控HregionServer的上线和下线信息,并实时通知给HMaster
③存储HBase的schema和table元数据
④HMaster需要知道哪些HRegionServer是活的可用的,及HRegionServer的位置信息,以便管理HRegionServer,这些信息都有Zookeepr提供!
Hbase优化
①RegionServ的region数量:一般每个RegionServer不要过1000,过多的region会导致产生较多的小文件,从而导致更多的compact,当有大量的超过5G的region并且RS总region数达到1000时,应该考虑扩容。
②建立表时:
1>如果不需要多版本则应该设置为VERSION=1。
2> 开启lzo或者snappy压缩,压缩会消耗一定的CPU,但是,磁盘IO和网络IO将获得极大的改善,大致可以压缩4~5倍;
3>合理的设计rowkey,在设计rowkey时需充分的理解现有业务并合理预见未来业务,不合理的rowkey设计将导致极差的hbase操作性能;
4>合理的规划数据量,进行预分区,避免在表使用过程中的不断split,并把数据的读写分散到不同的RS,充分的发挥集群的作用;
5>列族名称尽量短,比如:“f”,并且尽量只有一个列族;
6>视场景开启bloomfilter,优化读性能。
③Scan查询编程优化
1>如果是类似全表扫描这种查询,或者定期的任务,则可以设置scan的setCacheBlocks为false,避免无用缓存
2>关闭scanner,避免浪费客户端和服务器的内存
3>限定扫描范围:指定列簇或者指定要查询的列;
4>如果只查询rowkey时,则使用KeyOnlyFilter可大量减少网络消耗;
④Client端调优
1>hbase.client.write.buffer:写缓存大小,默认为2M,推荐设置为6M,单位是字节,当然不是越大越好,如果太大,则占用的内存太多;
2>hbase.client.scanner.caching:scan缓存,默认为1,太小,可根据具体的业务特征进行配置,原则上不可太大,避免占用过多的client和rs的内存,一般最大几百,如果一条数据太大,则应该设置一个较小的值,通常是设置业务需求的一次查询的数据条数,比如:业务特点决定了一次最多100条,则可以设置为100
⑤ZK调优
1>、zookeeper.session.timeout:默认值3分钟,不可配置太短,避免session超时,hbase停止服务,线上生产环境由于配置为1分钟,出现过2次该原因导致的hbase停止服务,也不可配置太长,如果太长,当rs挂掉,zk不能快速知道,从而导致master不能及时对region进行迁移。
2>zookeeper数量:至少5个节点。给每个zookeeper 1G左右的内存,最好有独立的磁盘。 (独立磁盘可以确保zookeeper不受影响).如果集群负载很重,不要把Zookeeper和RegionServer运行在同一台机器上面。就像DataNodes 和 TaskTrackers一样,只有超过半数的zk存在才会提供服务,比如:共5台,则最多只运行挂2台,配置4台与3台一样,最多只运行挂1台。
Bloom过滤器
BloomFilter在HBase中的作用?
Hbase利用BloomFilter来提高随机读写的性能,对于 顺序scan而言,设置BloomFilter是没有作用的,(在0.92之后如果设置了bloomfilter为ROWCOL,对于指定了qualiter的Scan有一定的优化)
BloomFilter在HBase中的开销?
BloomFilter是一个列族(cf)级别的配置属性,如果表中设置了BloomFilter那么HBase会在生成StoreFile时,包含一份BloomFilter结构的数据,称其为MetaBlock;MetaBlock与DataBlock(真实的KeyValue数据)一起由LRUBlockCache维护,所以开启BloomFilter会有一定的存储及内存cache开销。
不存在的回复100%准确,如果存在则最多有1%到2%的误差
Hbase块缓存
HBase提供了两种不同的BlockCache实现,来缓存从HDFS中读取的数据:默认的on-heap LruBlockCache和BucketCache(通常是off-heap)
LruBlockCache是原始实现,完全在Java堆内。 BucketCache是可选的,主要用于保持块缓存数据脱离堆,尽管BucketCache也可以是文件支持的缓存,但是BucketCache缓存在堆外容易造成内存污染即JVM的GC机制不能回收堆外的内存。