尧图精选

HBase 在日常中的使用

🕒 发布时间:2026/9/8 20:59:27 📁 来源:尧图网络
HBase是什么HBase是一个底层基于HDFS存储、开源的、面向列Column-Oriented、适合存储海量非结构化数据或半结构化数据的、具备高可靠性、高性能、可灵活扩展伸缩的、支持实时数据读写的分布式存储系统。关于存储在HBase 的表特征有表一个表通常可以有上亿行上百万列面向列面向列族的存储稀疏表中为空null的列不占用存储空间。HBase的结构HBase集群由主备Master进程和多个RegionServer进程组成。如下图所示图1中有几个角色其中包括HMaster、RegionServer、Zookeeper、HDFS、Client。HMaster在HA高可用模式下包含主用Master和备用Master。主用Master负责HBase中RegionServer的管理包括表的增删改查RegionServer的负载均衡Region分布调整Region分裂以及分裂后的Region分配RegionServer失效后的Region迁移等备用Master当主用Master故障时备用Master将取代主用Master对外提供服务。故障恢复后原主用Master降为备用。RegionServer负责提供表数据读写等服务是HBase的数据处理和计算单元负责维护一系列的region。RegionServer一般情况与HDFS集群的DataNode部署在一起实现数据的存储功能。Zookeeper用来为HBase集群中各进程提供分布式协作服务。各个RegionServer将自己的信息注册到ZooKeeper中主用Master据此感知各个RegionServer的健康状态等信息。HDFS作为HBase的底层数据存储底座为HBase提供高可靠的文件存储服务HBase的数据全部存储在HDFS中。Client使用HBase的RPC机制与Master、RegionServer进行通信。Client与Master进行管理类通信与RegionServer进行数据操作类通信。HBase原理HBase的数据模型HBase以表的形式存储数据数据模型如图所示。表中的数据划分为多个Region并由Master分配给对应的RegionServer进行管理。每个Region包含了表中一段RowKey区间范围内的数据HBase的一张数据表开始只包含一个Region随着表中数据的增多当一个Region的大小达到容量上限后会分裂成两个Region。您可以在创建表时定义Region的RowKey区间或者在配置文件中定义Region的大小。HBase数据模型主要包含以下几种Name Space 、Region、Row、Column Family、Column、Time Stamp、Cell。Name Space命名空间类似于关系型数据库的 DatabBase 概念每个命名空间下有多个表。HBase 有两个自带的命名空间分别是 hbase 和 defaulthbase 中存放的是 HBase 内置的表 default 表是用户默认使用的命名空间。Region类似于关系型数据库的表概念。不同的是HBase 定义表时只需要声明列族即可不需 要声明具体的列。这意味着往 HBase 写入数据时字段可以动态、按需指定。因此和关 系型数据库相比HBase 能够轻松应对字段变更的场景。RowHBase 表中的每行数据都由一个RowKey和多个Column列组成数据是按照 RowKey 的字典顺序存储的并且查询数据时只能根据 RowKey 进行检索所以 RowKey 的设计十分重 要。Column Family列族一个表在水平方向上由一个或多个Column Family组成。一个CFColumn Family可以由任意多个Column组成。Column是CF下的一个标签可以在写入数据时任意添加因此CF支持动态扩展无需预先定义Column的数量和类型。HBase中表的列非常稀疏不同行的列的个数和类型都可以不同。此外每个CF都有独立的生存周期TTL。可以只对行上锁对行的操作始终是原始的。Column列与传统的数据库类似HBase的表中也有列的概念列用于表示相同类型的数据。Time Stamp每次数据操作对应的时间戳数据按时间戳区分版本每个Cell的多个版本的数据按时间倒序存储。CellHBase最小的存储单元由Key和Value组成。Key由row、column family、column qualifier、timestamp、type、MVCC version这6个字段组成。Value就是对应存储的二进制数据对象。RegionServer数据存储HBase数据存储包括Store、MemStore、StoreFile、HFile、HLog。Store一个Region由一个或多个Store组成每个Store对应模型中的一个Column Family。MemStore一个Store包含一个MemStoreMemStore缓存客户端向Region插入的数据当RegionServer中的MemStore大小达到配置的容量上限时RegionServer会将MemStore中的数据“flush”到HDFS中。StoreFileMemStore的数据flush到HDFS后成为StoreFile随着数据的插入一个Store会产生多个StoreFile当StoreFile的个数达到配置的最大值时RegionServer会将多个StoreFile合并为一个大的StoreFile。HFileHFile定义了StoreFile在文件系统中的存储格式它是当前HBase系统中StoreFile的具体实现。HLogHLog日志保证了当RegionServer故障的情况下用户写入的数据不丢失RegionServer的多个Region共享一个相同的HLog。数据读写流程、flush时机、compact、Region split1. 数据写流程写流程1Client先访问zookeeper获取hbase:meta表位于哪个Region Server。2访问对应的Region Server获取hbase:meta表根据读请求的namespace:table/rowkey查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache方便下次访问。3与目标Region Server进行通讯4将数据顺序写入追加到WAL5将数据写入对应的MemStore数据会在MemStore进行排序6向客户端发送ack7等达到MemStore的刷写时机后将数据刷写到HFile。2. MemSore File刷写时机如图所示1.当某个memstroe的大小达到了hbase.hregion.memstore.flush.size默认值 128M其所在 region 的所有 memstore 都会刷写。当memstore的大小达到了hbase.hregion.memstore.flush.size默认值 128M * hbase.hregion.memstore.block.multiplier默认值 4时会阻止继续往该memstore写数据。2.当region server中memstore的总大小达到java_heapsize * hbase.regionserver.global.memstore.size默认值 0.4 * hbase.regionserver.global.memstore.size.lower.limit默认值 0.95region会按照其所有memstore的大小顺序由大到小依次进行刷写。直到region server中所有memstore的总大小减小到上述值以下。当region server中memstore的总大小达到java_heapsize*hbase.regionserver.global.memstore.size默认值 0.4时会阻止继续往所有的memstore写数据。3.到达自动刷写的时间也会触发memstore flush。自动刷新的时间间隔由该属性进行配置hbase.regionserver.optionalcacheflushinterval默认 1 小时。3. 数据读流程1Client先访问zookeeper获取hbase:meta表位于哪个Region Server。2访问对应的Region Server获取hbase:meta表根据读请求的namespace:table/rowkey查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache方便下次访问。3与目标Region Server进行通讯4分别在Block Cache读缓存MemStore和Store FileHFile中查询目标数据并将查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本time stamp或者不同的类型Put/Delete。5 将从文件中查询到的数据块BlockHFile数据存储单元默认大小为64KB缓存到Block Cache。6将合并后的最终结果返回给客户端。4.compact合并由于memstore每次刷写都会生成一个新的HFile且同一个字段的不同版本timestamp和不同类型Put/Delete有可能会分布在不同的HFile中因此查询时需要遍历所有的HFile。为了减少HFile的个数以及清理掉过期和删除的数据会进行StoreFile Compaction。Compaction分为两种分别是Minor Compaction和Major Compaction。Minor Compaction会将临近的若干个较小的HFile合并成一个较大的HFile但不会清理过期和删除的数据。Major Compaction会将一个Store下的所有的HFile合并成一个大HFile并且会清理掉过期和删除的数据。5. Region split默认情况下每个 Table起初只有一个Region随着数据的不断写入Region会自动进行拆分。刚拆分时两个子Region都位于当前的Region Server但处于负载均衡的考虑HMaster有可能会将某个Region转移给其他的Region Server。Region Split时机当1个region中 的 某 个Store下所有StoreFile的 总 大 小 超 过Min(R^2 *hbase.hregion.memstore.flush.size,hbase.hregion.max.filesize)该Region 就会进行拆分其 中R为当前Region Server中属于该Table的个数如下图所示。HBase 基础使用常用的的基本命令行操作包括put、get、scandelete这四种为表级别增、删、改、查操作其中put新增如果目标数据存在且时间戳大于等于插入时时间戳也为修改操作get、scan查询操作一种为指定rowkey获取单条数据一种为rowkey范围扫描获取一批数据delete删除一条数据以下几种为表级别DDLcreate、disable、enable、drop、truncate、desc、alter等其中create创建一张表需注意的是建表时无需指定字段类型但必须指定列族名称disable在删除表时需使用该命令事先将表停用enable 与disable相反将表上线drop 删除表truncate将表清空如果预先对表预分区请谨慎使用该命令该命令为删除后重建事先预分区的信息会丢失desc 查看表信息如使用什么压缩算法、记录版本数量等alter 修改表信息如将原先表snappy压缩算法修改为gzip等。具体相关命令细节可登录hbase shell 中使用help ‘命令’查看。HBase样例代码1.创建Configurationprivate static void init() throws IOException { //创建配置 conf HBaseConfiguration.create(); //windows操作系统 //String userdir TestMain.class.getClassLoader().getResource(conf).getPath() File.separator;[1] //linux操作系统 //String userdir System.getProperty(user.dir) File.separator conf File.separator; conf.addResource(new Path(userdir core-site.xml), false); conf.addResource(new Path(userdir hdfs-site.xml), false); conf.addResource(new Path(userdir hbase-site.xml), false); }首先创建配置对象通过类加载器将配置文件读取并添加资源到配置对象中。2.创建Connectionprublic Connection HBaseConn(Configuration conf){ TableName tableName TableName.valueOf(hbase_table_name); Connection conn ConnectionFactory.createConnection(conf); }通过传入配置对象获取HBase表名称获取HBase的连接对象。3.创建表public void CreateTable(TableName tableName) { //指定表描述符 TableDescriptorBuilder tdb TableDescriptorBuilder.newBuilder(tableName);1 //设置列族信息 ColumnFamilyDescriptorBuilder cdb ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(列族名)); // 设置HBase数据编码格式, HBase支持DIFF,FAST_DIFF,PREFIX三种 cdb.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF); //设置压缩格式,HBase支持gzip和snappy两种 cdb.setCompressionType(Compression.Algorithm.SNAPPY); tdb.setColumnFamily(cdb.build()); Admin admin null; try { admin conn.getAdmin(); if (!admin.tableExists(tableName)) { admin.createTable(tdb.build()); } else { LOG.warn(表已经存在); } } catch (IOException e) { LOG.error(创建表失败 ,e); } finally { if (admin ! null) { try { //关闭admin资源 admin.close(); } catch (IOException e) { LOG.error(关闭admin失败 ,e); } } } }大致流程如下1.创建表描述符2.创建列族描述符3.添加列族描述符到表描述符中4.获取Admin对象Admin提供了建表、创建列族、检查表是否存在、修改表结构和列族结构以及删除表等功能5.调用Admin的建表方法6.关闭admin资源。备注//设置编码算法HBase提供了DIFFFAST_DIFFPREFIX三种编码算法 cdb.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF); //设置文件压缩方式HBase默认提供了GZ和SNAPPY两种压缩算法 //其中GZ的压缩率高但压缩和解压性能低适用于冷数据 //SNAPPY压缩率低但压缩解压性能高适用于热数据 //建议默认开启SNAPPY压缩 cdb.setCompressionType(Compression.Algorithm.SNAPPY);4.删除表public void dropTable(TableName tableName) { Admin admin null; try { admin conn.getAdmin(); if (admin.tableExists(tableName)) { //第一步现将表下线 admin.disableTable(tableName); //第二步删除 admin.deleteTable(tableName); } LOG.info(删除成功); } catch (IOException e) { LOG.error(删除失败 ,e); } finally { if (admin ! null) { try { //关闭admin资源 admin.close(); } catch (IOException e) { LOG.error(关闭失败 ,e); } } } }5.插入数据public static void addRowData(String tableName, String rowKey, String columnFamily, String column, String value) throws IOException{ HTable hTable new HTable(conf, tableName); Put put new Put(Bytes.toBytes(rowKey)); put.add(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value)); hTable.put(put); hTable.close(); }大致流程如下1.创建HTable对象2.构建Put对象3.向Put对象中封装数据4.调用put方法插入数据5.关闭资源。6.删除数据public static void deleteMultiRow(String tableName, String... rows) throws IOException{ HTable hTable new HTable(conf, tableName); ListDelete deleteList new ArrayListDelete(); for(String row : rows){ Delete delete new Delete(Bytes.toBytes(row)); deleteList.add(delete); } hTable.delete(deleteList); hTable.close(); }大致流程如下1.创建HTable对象2.构建Delete 集合对象3.向Delete集合对象中封装Delete对象并封装数据4.调用delete方法插入数据5.关闭资源。备注使用java API 进行delete删除时使用使用columns加s的方法。7.使用Get读取数据public static void getRow(String tableName, String rowKey) throws IOException{ HTable table new HTable(conf, tableName); Get get new Get(Bytes.toBytes(rowKey)); Result result table.get(get); for(Cell cell : result.rawCells()){ System.out.println( 行 键 : Bytes.toString(result.getRow())); System.out.println( 列 族 Bytes.toString(CellUtil.cloneFamily(cell))); System.out.println( 列 : Bytes.toString(CellUtil.cloneQualifier(cell))); System.out.println( 值 : Bytes.toString(CellUtil.cloneValue(cell))); System.out.println(时间戳: cell.getTimestamp()); } table.close(); }大致流程如下1.创建HTable对象2.根据rowkey构建Get对象3.获取get返回结果4.遍历结果并打印5.关闭资源。8.使用Scan读取数据public static void getAllRows(String tableName) throws IOException{ HTable hTable new HTable(conf, tableName); Scan scan new Scan(); ResultScanner resultScanner hTable.getScanner(scan); for(Result result : resultScanner){ Cell[] cells result.rawCells(); for(Cell cell : cells){ System.out.println( 行 键 : Bytes.toString(CellUtil.cloneRow(cell))); System.out.println( 列 族 Bytes.toString(CellUtil.cloneFamily(cell))); System.out.println( 列 : Bytes.toString(CellUtil.cloneQualifier(cell))); System.out.println( 值 : Bytes.toString(CellUtil.cloneValue(cell))); } } }大致流程如下1.创建HTable对象2.根据rowkey范围构建Scan对象3.获取scan返回结果4.遍历结果并打印5.关闭资源。9.HBase对接HiveCREATE EXTERNAL TABLE hive_external_table_name( rowkey string COMMENT , col1 string COMMENT , col2 string COMMENT , col3 string COMMENT , col4 string COMMENT , col5 string COMMENT ) ROW FORMAT SERDE org.apache.hadoop.hive.hbase.HBaseSerDe STORED BY org.apache.hadoop.hive.hbase.HBaseStorageHandler WITH SERDEPROPERTIES ( hbase.columns.mapping:key,cf1:col1,cf1:col2,cf1:col3,cf1:col4,cf1:col5, serialization.format1) TBLPROPERTIES ( hbase.mapred.output.outputtableHBase_namespace:HBase_table_name,hbase.table.nameHBase_namespace:HBase_table_name);HBase与Hive的映射是通过Hive的HBaseStorageHandler组件实现的它充当了Hive和HBase之间的桥梁使Hive能够将HBase表映射为Hive外部表从而通过SQL语句操作HBase数据。需要注意的是现版本通过hive创建HBase映射表还无法获取HBase表中每个字段的时间戳但可以获取最大的时间戳作为HQL条件查询。通过Hive映射表写入HBase时时间戳会根据系统时间生成如果HBase中timestamp值取值为业务时间那么在后续数据重新入库时将收到影响导致数据无法写入的风险HBase数据迁移1.原始数据表进行快照 : snapshot hbase_src_tablename,hbase_src_tablename_snapshot 2.将表快照进行迁移 linux hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot \ -Dsnapshot.export.skip.tmptrue \ -snapshot hbase_src_table_name_backup_snapshot \ --将要迁移的快照和快照那一时刻表的数据 -copy-from hdfs://源集群NN IP:port/hbase \ --从哪个hdfs集群(旧) -copy-to hdfs://目的集群NN IP:port/hbase \ --到哪个hdfs集群(新) -mappers 16 \ --mapper的个数 -bandwidth 20 --带宽 3.对迁移过来的表快照恢复:clone_snapshot hbase_src_tablename_snapshot,hbase_des_tablename 4.major_compact hbase_des_tablename 备注 1.创建一个快照后对应hdfs /hbase/.hbase-snapshot目录下会记录一个快照名的目录里面有一个文件记录打快照的那张表下打快照那一刻起所有的storefile 2.将快照恢复到另外一张新表后在没有执行major_conpact命令之前这张新表中storefile所存储的是一个引用例如 原始表Aregion名-Bstorefile名如果基表不删除在合并过后可以通过从archive目录原始表Aregion名-Bstorefile名进行查看。 3.在原始表也就是创建快照的基表进行合并的时候如果storefile还存在引用那么不会直接删除而是将数据保存到hdfs路径下的archive特别说明使用HBase snapshot的方式做数据迁移时一定要核对表是否完全合并完成HBase表目录下所有StoreFile中没有不规则的命名方式“原始表Aregion名-Bstorefile名”。只有在完全合并完成后才意味着所有链接文件的数据已经合并到表目录下这时才可以将快照进行删除不然会导致Region处于RIT状态导致丢数据的风险。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →