大数据技术之HBase原理与实战归纳分享-中( 四 )


  • 当 1 个 region 中 的 某 个 Store 下 所 有 StoreFile 的 总 大 小 超 过hbase.hregion.max.filesize (10G),该 Region 就会进行拆分 。0.94 版本之后,2.0 版本之前 => IncreasingToUpperBoundRegionSplitPolicy
  • 当 1 个 region 中 的 某 个 Store 下 所 有 StoreFile 的 总 大 小 超 过Min(initialSize*R^3 ,hbase.hregion.max.filesize"),该 Region 就会进行拆分 。其中 initialSize 的默认值为 2 * hbase.hregion.memstore.flush.size,R 为当前 Region Server 中属于该 Table 的Region 个数(0.94 版本之后) 。具体的切分策略为:
    • 第一次 split:1^3 * 256 = 256MB
    • 第二次 split:2^3 * 256 = 2048MB
    • 第三次 split:3^3 * 256 = 6912MB
    • 第四次 split:4^3 * 256 = 16384MB > 10GB,因此取较小的值 10GB
    • 后面每次 split 的 size 都是 10GB 了 。2.0 版本之后 => SteppingSplitPolicy
  • Hbase 2.0 引入了新的 split 策略:如果当前 RegionServer 上该表只有一个 Region,按照 2 * hbase.hregion.memstore.flush.size 分裂,否则按照 hbase.hregion.max.filesize 分裂 。
JAVA API编程准备新建项目后在 pom.xml 中添加下面依赖,注意:会报错 javax.el 包不存在 , 是一个测试用的依赖 , 不影响使用 。
<dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>2.5.0</version><exclusions><exclusion><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId><version>3.0.1-b12</version></dependency>在 resources 文件夹中创建配置文件 hbase-site.xml,添加以下内容
<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="https://www.huyubaike.com/biancheng/configuration.xsl"?><configuration><property><name>hbase.zookeeper.quorum</name><value>hadoop102,hadoop103,hadoop104</value><description>The directory shared by RegionServers.</description></property></configuration>示例根据官方 API 介绍,HBase 的客户端连接由 ConnectionFactory 类来创建,用户使用完成 之后需要手动关闭连接 。同时连接是一个重量级的,推荐一个进程使用一个连接,对 HBase 的命令通过连接中的两个属性 Admin 和 Table 来实现 。
封装连接类HBaseConnection.java,使用类单例模式,确保使用一个连接 , 可以同时用于多个线程 。
package cn.itxs.hbasedemo;import org.apache.hadoop.hbase.client.Connection;import org.apache.hadoop.hbase.client.ConnectionFactory;import java.io.IOException;public class HBaseConnection {//声明一个静态属性public static Connection connection = null;static{//1.创建连接配置对象//Configuration conf = new Configuration();//2.添加配置参数//conf.set("hbase.zookeeper.quorum","hadoop102,hadoop103,hadoop104");//因为已经把配置参数写到hbase-site.xml中 , 所以直接连接//3.创建连接//默认使用同步连接try {connection = ConnectionFactory.createConnection();} catch (IOException e) {System.out.println("连接失败");e.printStackTrace();}}/*** 关闭连接方法* @throws IOException*/public static void closeConnection() throws IOException {if (connection != null){// 关闭connection.close();}}public static void main(String[] args) throws IOException {//可以使用异步连接//CompletableFuture<AsyncConnection> asyncConnection = ConnectionFactory.createAsyncConnection();//4.使用连接System.out.println(connection);//在main最后关闭连接HBaseConnection.closeConnection();}}封装DDL操作类HBaseDDL.java
package cn.itxs.hbasedemo;import org.apache.hadoop.hbase.NamespaceDescriptor;import org.apache.hadoop.hbase.TableName;import org.apache.hadoop.hbase.client.*;import org.apache.hadoop.hbase.util.Bytes;import java.io.IOException;public class HBaseDDL {// 添加静态属性 connection 指向单例连接public static Connection connection= HBaseConnection.connection;/*** 创建命名空间* @param namespace 命名空间名称*/public static voidcreateNamespace(String namespace) throws IOException {//1.获取admin//admin 连接是轻量级的,不是线程安全的不推荐池化,或者缓存这个连接Admin admin = connection.getAdmin();//2.调用方法,创建命名空间/* 代码相对shel1更加底层 所以shel1能够实现的功能代码一定能实现11所以需要填写完整的命名空间描述*///2.1 创建命名空间描述建造者=> 设计师NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(namespace);//2.2 给命名空间添加需求builder.addConfiguration("user","mazankang");//2.3 使用builder构造出对应的NamespaceDescriptor添加完参数的对象//完成创建// 创建命名空间出现的问题都属于本方法自身的问题不应该抛出异常try {admin.createNamespace(builder.build());} catch (IOException e) {System.out.println("命名空间已经存在");e.printStackTrace();}//3 关闭adminadmin.close();}/***判断表格是否存在* @param namespace 命名空间名称* @param tableName 表格名称* @return true表示存在*/public static boolean isTableExists(String namespace,String tableName) throws IOException {//1.获取adminAdmin admin = connection.getAdmin();//2.使用对象的方法boolean b = false;try {b = admin.tableExists(TableName.valueOf(namespace, tableName));} catch (IOException e) {e.printStackTrace();}admin.close();return b;}/*** 创建表格* @param namespace 命名空间名称* @param tableName表格名称* @param columnFamilys 列族名称可以有多个*/public static void createTable(String namespace,String tableName,String... columnFamilys) throws IOException {//判断至少有一个列族if (columnFamilys.length ==0 ){System.out.println("创建表格需要至少一个列族");return;}//判断表格是否存在if (isTableExists(namespace,tableName)){System.out.println("表格已经存在");return;}//获取adminAdmin admin = connection.getAdmin();//2.调用方法创建表格//2.1创建表格描述的建造者TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf(namespace, tableName));//2.2添加参数for (String columnFamily : columnFamilys) {//2.3创建列族描述的建造者ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily));//2.4对应当前列族添加版本//添加版本参数columnFamilyDescriptorBuilder.setMaxVersions(5);//版本// ------>>>>>>> 在这里可以加创造表属性所需要的所以方法//2.5创建添加完参数的列族描述tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptorBuilder.build());}//2.6创建对应的表格描述try {admin.createTable(tableDescriptorBuilder.build());} catch (IOException e) {e.printStackTrace();}admin.close();}/*** 修改表格中一个列族的版本* @param namespace 命名空间名称* @param tableName 表格名称* @param columnFamily 列族名称* @param version 版本号*/public static void modifyTable(String namespace,String tableName,String columnFamily,int version) throws IOException {//判断表格是否存在if (!isTableExists(namespace,tableName)){System.out.println("表格不存在");return;}//1.获取adminAdmin admin = connection.getAdmin();//2.调用方法修改表格//2.0 获取之前的表格描述TableDescriptor descriptor = admin.getDescriptor(TableName.valueOf(namespace, tableName));// 需要填写旧的列族描述ColumnFamilyDescriptor columnFamily1 = descriptor.getColumnFamily(Bytes.toBytes(columnFamily));//如果使用填写tableName的方法相当于创建了一个新的表格描述建造者没有之前的信息//1如果想要修改之前的信息必须调用方法填写一个旧的表格描述//2.1 创建一个表格描述建造者//--------------------------TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(descriptor);//2.2 对应建造者进行表格数据的修改//创建列族描述建造者ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder =ColumnFamilyDescriptorBuilder.newBuilder(columnFamily1);//修改对应的版本columnFamilyDescriptorBuilder.setMaxVersions(version);//此处修改的时候 如果是新创建的 别的参数会初始化tableDescriptorBuilder.modifyColumnFamily(columnFamilyDescriptorBuilder.build());try {admin.modifyTable(tableDescriptorBuilder.build());} catch (IOException e) {throw new RuntimeException(e);}//关闭admin.close();}/*** 删除表格* @param namespace 命名空间名称* @param tableName 表格名称* @return true 表示删除成功*/public static boolean deleteTable(String namespace,String tableName) throws IOException {//1判断表格是否存在if (!isTableExists(namespace,tableName)) {System.out.println("表格不存在");return false;}//2.获取adminAdmin admin = connection.getAdmin();// 3.调用 相关的方法删除表格try {//HBase删除表格之前 一定要标记表格为不可用disableTableName tableName1 = TableName.valueOf(namespace, tableName);admin.disableTable(tableName1);admin.deleteTable(tableName1);} catch (IOException e) {throw new RuntimeException(e);}//关闭adminadmin.close();return true;}}

推荐阅读