十万个为什么之Hbase篇

1、为什么Hadoop可以为Hbase提供高容错性?

因为Hadoop跟Hbase都是出至于Apache基金会,Hbase建立于Hadoop之上,habse以storeFile二进制流的形式将数据存储在hdfs的block块中;hdfs的存储方式就是多副本block块,出现问题可以使用副本,而且hdfs会定期检查block块是否损坏;
注意:hdfs并不知道Hbase存储的是什么,只将其当作二进制文件;

2、为什么预分region可以解决Hbase的热点问题?

因为region是Hbase的基本单元,假设有一个订单表,该表只有一个region,当多个客户端对该表进行访问时,造成了热点问题,可以在建表时进行region预分区,可使用java API 或sql

例如:sql进行预分区

>例如:创建一个表名为tt  列簇为tt_info的表
>语句为: creat ‘tt’,‘tt_info’,{splits=>['A','B','C','D']}
>假设是按照该表中的订单号:添加前缀或者取哈希值,分成若干个分区ABCD,他们放到不同的region中,每个region由不同的region Server管理;再有客户端进行访问的时候只会影响要访问的regio

Hbase API进行预分区

import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.regionserver.KeyPrefixRegionSplitPolicy;
import org.apache.hadoop.hbase.util.Bytes;

public class HBasePreSplitExample {
  public static void main(String[] args) throws Exception {
    // 定义表名、列族名以及预分区的分界点
    String tableName = "orders";
    String columnFamily = "order_info";
    byte[][] splits = new byte[][] {
        Bytes.toBytes("A"),
        Bytes.toBytes("B"),
        Bytes.toBytes("C"),
        Bytes.toBytes("D")
    };

    // 创建 HBase 连接
    org.apache.hadoop.conf.Configuration config = HBaseConfiguration.create();
    Connection connection = ConnectionFactory.createConnection(config);
    Admin admin = connection.getAdmin();

    // 构建表的描述信息
    TableDescriptor tableDescriptor =
        TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName))
            .setColumnFamily(ColumnFamilyDescriptorBuilder.of(columnFamily))
            .setRegionSplitPolicyClassName(KeyPrefixRegionSplitPolicy.class.getName())
            .setValue(TableDescriptorBuilder.SPLIT_POLICY, KeyPrefixRegionSplitPolicy.class.getName())
            .build();

    // 创建带有预分区的表
    admin.createTable(tableDescriptor, splits);
    System.out.println("Table created with pre-split regions.");
  }
}

代码逐句解析:
1.import 语句导入了 HBase API 所需的类和接口。
2.HBasePreSplitExample 是一个 Java 类,用于创建带有预分区的 HBase 表。
3.main 方法是 Java 程序的入口,其中 throws Exception 表示可能会抛出异常。
4.tableName、columnFamily 和 splits 分别表示表名、列族名以及预分区的分界点,这里我们将订单号按照 A、B、C、D 四个前缀进行预分区。
5.config 表示 HBase 的配置信息,Connection 表示与 HBase 的连接,Admin 表示 HBase 的管理员对象。
6.TableDescriptorBuilder 用于构建 HBase 表的描述信息,TableDescriptor 表示 HBase 表的描述。
7.setColumnFamily 方法设置表的列族信息,使用 ColumnFamilyDescriptorBuilder.of() 方法创建列族描述。
8.setRegionSplitPolicyClassName 和 setValue 方法设置预分区策略为 KeyPrefixRegionSplitPolicy。
9.admin.createTable() 方法用于创建 HBase 表,其中包括表的描述信息和预分区的分界点。
10.System.out.println() 方法用于在控制台输出信息

3、Hbase不支持sql查询该怎么办?
可以使用apache phoenix在Hbase上完成sql查询,他是Hbase 的sql层;需要先在phoenix中建表,并将数据导入到Hbse中才能使用sql查询数据;
以下是安装过程及示例:

首先,需要在 HBase 集群中安装并启动 Phoenix。可以从 Phoenix 的官方网站(https://phoenix.apache.org/)下载安装包并进行安装。安装完成后,可以使用如下命令启动 Phoenix:
Copy
$ sqlline.py localhost:2181:/hbase-unsecure
其中,2181 是 HBase 集群的 ZooKeeper 端口号,/hbase-unsecure 是 HBase 的 ZooKeeper 根节点。
接下来,在 Phoenix 中创建表并插入数据。可以使用如下 SQL 语句创建一个名为 orders 的表:
Copy
CREATE TABLE orders (
order_id varchar primary key,
order_date date,
order_status varchar
);
然后,可以使用如下 SQL 语句插入数据:
scheme
Copy
UPSERT INTO orders (order_id, order_date, order_status) VALUES (‘order_001’, ‘2022-05-08’, ‘completed’);
UPSERT INTO orders (order_id, order_date, order_status) VALUES (‘order_002’, ‘2022-05-09’, ‘processing’);
UPSERT INTO orders (order_id, order_date, order_status) VALUES (‘order_003’, ‘2022-05-10’, ‘canceled’);
最后,可以使用 Phoenix 执行 SQL 查询语句来查询数据。例如,可以使用如下 SQL 语句查询 order_id 为 ‘order_001’ 的订单状态:
Copy
SELECT order_status FROM orders WHERE order_id = ‘order_001’;
查询结果如下:
asciidoc
Copy
±-------------+
| ORDER_STATUS |
±-------------+
| completed |
±-------------+

4、健康小提示:健康是开发的基本,起来活动活动吧;

手握紧30秒再松开3秒内恢复血色表达血管无堵塞,5-10秒有轻微堵塞;

5、为什么当region被删除或者被重新分配时,会发生数据不在本地的情况?

因为当region被删除时,Hbase会对region Server重新进行负载均衡,此时要访问该数据就需要通过别的regionServer重新访问;
为此有region预读取、region缓存,数据块缓存等;除此之外为了保证数据的可靠性在不同regionServer上添加副本

6、为什么put数据后在hdfs中查看不到?

可能因为你添加的数据小于128MB此时的数据还在memstore中,没有触发自动刷新;可以手动刷新:
1.使用 flush 命令:可以使用 HBase Shell 中的 flush 命令手动将 MemStore 中的数据刷新到 StoreFile 中。具体命令如下:
hbase> flush ‘table_name’
其中,table_name 是需要刷新数据的表名。
2.使用 Java API:具体代码如下:
HBaseAdmin admin = new HBaseAdmin(conf);
admin.flush(tableNameAsString);
其中,tableNameAsString 是需要刷新数据的表名。

需要注意的是,手动刷新 MemStore 中的数据会导致性能下降,因此应该在必要时才使用。另外,刷新操作可能会导致数据的不一致性,因此需要谨慎使用,并在刷新操作完成后进行数据的校验和验证

7、为什么Hbase不能像mysql一样对列进行查询?

因为Hbase的列名和个数有我们自定义的,之所以不能像mysql一样,是因为不知道列的个数;

8、数据都是存储在hdfs上,为什么hdfs不支持删改,而Hbase可以呢?

Hbase的数据是以HFile的形式存储在hdfs上的,hdfs上的数据是以block块的形式存储;Hbase 的数据删除不是真正的删除,而是要对删除的数据打一个标记,由HMster每隔一小时清除有标记的数据;我们再次查询的时候,是查询不到有标记的数据的;“修改”是对数据put两次,Hbase获取最新的信息,原先的数据也会这样被HMaster清除

9、为什么创建了一个表对其写入了数据却不能读取?

Hbase创建一个新表默认处于禁用状态,可以写入数据但不能读取;需要输入 enable ‘表名’ 将该表设置为有效状态,此状态Hbase会自动维表创建region维护并在多个regionServer上保存数据副本;
对于不想用的表可用disable ‘表名’ 将该表设置为无效状态,配合delete命令删除表,释放资源;
为了避免此问题;在创建Hbase表的时候就可以指定{enable=> ‘ture’}
例子:create ‘example_table’, {NAME => ‘cf1’}, {NAME => ‘cf2’}, {VERSIONS => 3, ENABLED => ‘true’}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值