Hbase入门篇03---Java API使用,HBase高可用配置和架构设计

news2024/9/21 20:51:08

Hbase入门篇03---Java API使用,HBase高可用配置和架构设计

  • 需求
    • 环境搭建
    • 表的CRUD
        • 命令执行卡住不动 ?
        • RegionServer只在本地127.0.0.1监听16020端口导致外网连接被拒
        • RegionServer所在主机的/etc/hosts文件存在额外的回环地址映射信息,导致客户端拿到无法识别的主机名
    • 数据的CRUD
    • 数据的导入导出
      • Import JOB
    • 数据查询
  • HBase高可用
    • HBase高可用简介
    • 搭建HBase高可用
  • HBase架构
  • 常见Bug记录
  • 本部分思维导图


需求

某某自来水公司,需要存储大量的缴费明细数据。以下截取了缴费明细的一部分内容。

用户id姓名用户地址性别缴费时间表示数(本次)表示数(上次)用量(立方)合计金额查表日期最迟缴费日期
4944191登卫红贵州省铜仁市德江县7单元267室2020-05-10308.1283.1251502020-04-252020-06-09

因为缴费明细的数据记录非常庞大,该公司的信息部门决定使用HBase来存储这些数据。并且,他们希望能够通过Java程序来访问这些数据。


环境搭建

  • 引入依赖
    <repositories>
        <repository>
            <id>aliyun</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <target>1.8</target>
                    <source>1.8</source>
                </configuration>
            </plugin>
        </plugins>
    </build>
  • 如果在 settings.xml 文件和当前项目的 pom.xml 文件中都指定了同一个 repository 配置,那么 pom.xml 中的配置会覆盖 settings.xml 中的配置。
  • 这意味着,如果在 pom.xml 中定义了特定的存储库,Maven 将会使用 pom.xml 中指定的配置,而不是 settings.xml
    中的配置。
  • 但是,如果在 pom.xml 中没有指定,Maven 会尝试在 settings.xml 中查找相应的配置。
  • 如果在settings.xml 中也没有找到,则 Maven 将默认使用 Maven 中央存储库。
  • 复制HBase和Hadoop配置文件
    • 将以下三个配置文件复制到resource目录中
      • hbase-site.xml
        • 从Linux中下载:sz /export/server/hbase-2.1.0/conf/hbase-site.xml
      • core-site.xml
        • 从Linux中下载:sz /export/server/hadoop-2.7.5/etc/hadoop/core-site.xml
      • log4j.properties

注意:请确认配置文件中的服务器节点hostname/ip地址配置正确

在访问HBase时,需要使用HBase和Hadoop的相关配置信息来与集群进行通信。通常情况下,这些配置文件位于集群中的节点上,Java应用程序需要知道这些配置信息才能连接到HBase集群。因此,将这些配置文件复制到Java项目中可以方便Java应用程序获取配置信息,从而连接到HBase集群。如果不将这些配置文件复制到Java项目中,则需要手动配置Java应用程序中的相关配置信息。

sz 命令是一种用于从远程服务器下载文件的命令。在该命令中,/export/server/hbase-2.1.0/conf/hbase-site.xml 是要下载的文件的路径。该命令会将文件下载到当前目录中。通常,sz 命令需要在客户端终端中运行,以从远程服务器下载文件。


  • 创建HBase连接及Admin管理对象
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import java.io.IOException;

public class TableAmdinTest {
    private Configuration configuration;
    private Connection connection;
    private Admin admin;

    @BeforeTest
    public void beforeTest() throws IOException {
        configuration = HBaseConfiguration.create();
        //可以不引入hbase-site.xml配置文件,手动指定zk地址,客户端从zk拉取,获取master和regionServer的地址
        configuration.set("hbase.zookeeper.quorum", "node1");
        connection = ConnectionFactory.createConnection(configuration);
        admin = connection.getAdmin();
    }
    
    @AfterTest
    public void afterTest() throws IOException {
        admin.close();
        connection.close();
    }
}


表的CRUD

创建表:

创建一个名为WATER_BILL的表,包含一个列蔟C1。

  • 调用tableExists判断表是否存在
  • 在HBase中,要去创建表,需要构建TableDescriptor(表描述器)、ColumnFamilyDescriptor(列蔟描述器),这两个对象不是直接new出来,是通过builder来创建的
  • 将列蔟描述器添加到表描述器中
  • 使用admin.createTable创建表
    /**
     * 创建一个名为WATER_BILL的表,包含一个列蔟C1
     */
    @Test
    public void createTableTest() throws IOException {
        // 表名
        String TABLE_NAME = "WATER_BILL";
        // 列蔟名
        String COLUMN_FAMILY = "C1";

        // 1. 判断表是否存在
        if (admin.tableExists(TableName.valueOf(TABLE_NAME))) {
            return;
        }

        // 2. 构建表描述构建器
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf(TABLE_NAME));

        // 3. 构建列蔟描述构建器
        ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(COLUMN_FAMILY));

        // 4. 构建列蔟描述
        ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();

        // 5. 构建表描述
        // 添加列蔟
        tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();

        // 6. 创建表
        admin.createTable(tableDescriptor);
    }

注意:

  • 在HBase中所有的数据都是以byte[]形式来存储的,所以需要将Java的数据类型进行转换
  • 经常会使用到一个工具类:Bytes(hbase包下的Bytes工具类)
  • 这个工具类可以将字符串、long、double类型转换成byte[]数组
  • 也可以将byte[]数组转换为指定类型

删除表:

    @Test
    public void dropTable() throws IOException {
        // 表名
        TableName tableName = TableName.valueOf("WATER_BILL");

        // 1. 判断表是否存在
        if (admin.tableExists(tableName)) {
            // 2. 禁用表
            admin.disableTable(tableName);
            // 3. 删除表
            admin.deleteTable(tableName);
        }
    }

此处列举HBase Java客户端使用过程中可能会遇到的一些坑:

命令执行卡住不动 ?

HBase Java客户端在调用相关方法时,会自动进行重试和超时机制,如果一直无法建立连接或响应,则可能会导致方法一直卡住。

为了避免这种情况,可以设置一个较短的超时时间或者关闭自动重试机制。可以使用以下方法实现:

  • 设置超时时间:
    • 可以通过调用HBase Configuration对象的set方法设置“hbase.client.operation.timeout”参数的值,以毫秒为单位。
    • 例如,设置为1秒钟:
Configuration conf = HBaseConfiguration.create();
conf.setInt("hbase.client.operation.timeout", 1000);
  • 关闭自动重试:
    • 可以通过调用HBase Configuration对象的set方法设置“hbase.client.retries.number”参数的值为0,表示关闭自动重试机制。
    • 例如:
Configuration conf = HBaseConfiguration.create();
conf.setInt("hbase.client.retries.number", 0);

但是需要注意,关闭自动重试机制可能会导致某些操作失败。因此,需要根据实际情况选择适当的配置。


上面的配置只是为了让客户端出现连接异常时,能够快速失败,而不是不断的重试和超时等待,导致我们无法及时感知错误发生。

当异常抛出来之后,下面就是根据异常分类处理了,下面我列举我遇到的一些异常情况:

RegionServer只在本地127.0.0.1监听16020端口导致外网连接被拒

Caused by: java.net.ConnectException: Call to node2/xxx:16020 failed on connection exception: org.apache.hbase.thirdparty.io.netty.channel.ConnectTimeoutException: connection timed out: node2/123.60.166.193:16020
	at org.apache.hadoop.hbase.ipc.IPCUtil.wrapException(IPCUtil.java:165)
	at org.apache.hadoop.hbase.ipc.AbstractRpcClient.onCallFinished(AbstractRpcClient.java:390)
	at org.apache.hadoop.hbase.ipc.AbstractRpcClient.access$100(AbstractRpcClient.java:95)
	at org.apache.hadoop.hbase.ipc.AbstractRpcClient$3.run(AbstractRpcClient.java:410)
	at org.apache.hadoop.hbase.ipc.AbstractRpcClient$3.run(AbstractRpcClient.java:406)

解决方法,在hbase-site.xml配置文件中配置RegionServer在0.0.0.0地址上监听16020端口:

  <property>
    <name>hbase.regionserver.ipc.address</name>
    <value>0.0.0.0</value>
  </property>

RegionServer所在主机的/etc/hosts文件存在额外的回环地址映射信息,导致客户端拿到无法识别的主机名

在这里插入图片描述


数据的CRUD

  • 插入姓名列数据
    • 在表中插入一个行,该行只包含一个列。
ROWKEY姓名(列名:NAME)
4944191登卫红
  • 首先要获取一个Table对象,这个对象是要和HRegionServer节点连接,所以将来HRegionServer负载是比较高的
  • HBase的connection对象是一个重量级的对象,将来编写代码(Spark、Flink)的时候,避免频繁创建,使用一个对象就OK,因为它是线程安全的
Connection creation is a heavy-weight operation. Connection implementations are thread-safe
  • Table这个对象是一个轻量级的,用完Table需要close,因为它是非线程安全的
Lightweight. Get as needed and just close when done.
  • 需要构建Put对象,然后往Put对象中添加列蔟、列、值

  • 当执行一些繁琐重复的操作用列标记:

    • ctrl + shift + ←/→,可以按照单词选择,非常高效
 @Test
    public void addTest() throws IOException {
        // 1.使用Hbase连接获取Htable
        TableName waterBillTableName = TableName.valueOf("WATER_BILL");
        Table waterBillTable = connection.getTable(waterBillTableName);

        // 2.构建ROWKEY、列蔟名、列名
        String rowkey = "4944191";
        String cfName = "C1";
        String colName = "NAME";

        // 3.构建Put对象(对应put命令)
        Put put = new Put(Bytes.toBytes(rowkey));

        // 4.添加姓名列
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colName)
                , Bytes.toBytes("登卫红"));

        // 5.使用Htable表对象执行put操作
        waterBillTable.put(put);
        // 6. 关闭表
        waterBillTable.close();
    }
  • 插入其他列
列名说明
ADDRESS用户地址贵州省铜仁市德江县7单元267室
SEX性别
PAY_DATE缴费时间2020-05-10
NUM_CURRENT表示数(本次)308.1
NUM_PREVIOUS表示数(上次)283.1
NUM_USAGE用量(立方)25
TOTAL_MONEY合计金额150
RECORD_DATE查表日期2020-04-25
LATEST_DATE最迟缴费日期2020-06-09
    @Test
    public void addTest1() throws IOException {
        // 1.使用Hbase连接获取Htable
        TableName waterBillTableName = TableName.valueOf("WATER_BILL");
        Table waterBillTable = connection.getTable(waterBillTableName);

        // 2.构建ROWKEY、列蔟名、列名
        String rowkey = "4944191";
        String cfName = "C1";
        String colName = "NAME";
        String colADDRESS = "ADDRESS";
        String colSEX = "SEX";
        String colPAY_DATE = "PAY_DATE";
        String colNUM_CURRENT = "NUM_CURRENT";
        String colNUM_PREVIOUS = "NUM_PREVIOUS";
        String colNUM_USAGE = "NUM_USAGE";
        String colTOTAL_MONEY = "TOTAL_MONEY";
        String colRECORD_DATE = "RECORD_DATE";
        String colLATEST_DATE = "LATEST_DATE";

        // 3.构建Put对象(对应put命令)
        Put put = new Put(Bytes.toBytes(rowkey));

        // 4.添加姓名列
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colName)
                , Bytes.toBytes("登卫红"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colADDRESS)
                , Bytes.toBytes("贵州省铜仁市德江县7单元267室"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colSEX)
                , Bytes.toBytes("男"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colPAY_DATE)
                , Bytes.toBytes("2020-05-10"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colNUM_CURRENT)
                , Bytes.toBytes("308.1"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colNUM_PREVIOUS)
                , Bytes.toBytes("283.1"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colNUM_USAGE)
                , Bytes.toBytes("25"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colTOTAL_MONEY)
                , Bytes.toBytes("150"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colRECORD_DATE)
                , Bytes.toBytes("2020-04-25"));
        put.addColumn(Bytes.toBytes(cfName)
                , Bytes.toBytes(colLATEST_DATE)
                , Bytes.toBytes("2020-06-09"));

        // 5.使用Htable表对象执行put操作
        waterBillTable.put(put);

        // 6. 关闭表
        waterBillTable.close();
    }

  • 查看一条数据
    @Test
    public void getOneTest() throws IOException {
        // 1. 获取HTable
        TableName waterBillTableName = TableName.valueOf("WATER_BILL");
        Table waterBilltable = connection.getTable(waterBillTableName);

        // 2. 使用rowkey构建Get对象
        Get get = new Get(Bytes.toBytes("4944191"));

        // 3. 执行get请求
        Result result = waterBilltable.get(get);

        // 4. 获取所有单元格
        List<Cell> cellList = result.listCells();

        // 打印rowkey
        System.out.println("rowkey => " + Bytes.toString(result.getRow()));

        // 5. 迭代单元格列表
        for (Cell cell : cellList) {
            // 打印列蔟名
            System.out.print(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
            System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));

        }

        // 6. 关闭表
        waterBilltable.close();
    }

在这里插入图片描述


  • 删除一条数据
    // 删除rowkey为4944191的整条数据
    @Test
    public void deleteOneTest() throws IOException {
        // 1. 获取HTable对象
        Table waterBillTable = connection.getTable(TableName.valueOf("WATER_BILL"));

        // 2. 根据rowkey构建delete对象
        Delete delete = new Delete(Bytes.toBytes("4944191"));

        // 3. 执行delete请求
        waterBillTable.delete(delete);

        // 4. 关闭表
        waterBillTable.close();
    }

数据的导入导出

Import JOB

在HBase中,有一个Import的MapReduce作业,可以专门用来将数据文件导入到HBase中。

  • 用法:
hbase org.apache.hadoop.hbase.mapreduce.Import 表名 HDFS数据文件路径

导入数据演示:

  • 将文件上传到hdfs中
hadoop fs -mkdir -p /water_bill/output_ept_10W
hadoop fs -put part-m-00000_10w /water_bill/output_ept_10W
  • 启动YARN集群
start-yarn.sh
  • 使用以下方式来进行数据导入
hbase org.apache.hadoop.hbase.mapreduce.Import WATER_BILL /water_bill/output_ept_10W

导出数据演示:

hbase org.apache.hadoop.hbase.mapreduce.Export WATER_BILL /water_bill/output_ept_10W_export

数据查询

需求: 查询2020年6月份所有用户的用水量

  • 需求分析
    • 在Java API中,我们也是使用scan + filter来实现过滤查询。2020年6月份其实就是从2020年6月1日到2020年6月30日的所有抄表数据。

注意:

  • ResultScanner需要手动关闭,这个操作是比较消耗资源的,用完就应该关掉,不能一直都开着
  • 扫描使用的是Scan对象
  • SingleColumnValueFilter——过滤单列值的过滤器
  • FilterList——是可以用来组合多个过滤器
    // 查询2020年6月份所有用户的用水量数据
    @Test
    public void queryTest1() throws IOException {
        // 1. 获取表
        Table waterBillTable = connection.getTable(TableName.valueOf("WATER_BILL"));
        // 2. 构建scan请求对象
        Scan scan = new Scan();
        // 3. 构建两个过滤器
        // 3.1 构建日期范围过滤器(注意此处请使用RECORD_DATE——抄表日期比较
        SingleColumnValueFilter startDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1")
                , Bytes.toBytes("RECORD_DATE")
                , CompareOperator.GREATER_OR_EQUAL
                , Bytes.toBytes("2020-06-01"));

        SingleColumnValueFilter endDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1")
                , Bytes.toBytes("RECORD_DATE")
                , CompareOperator.LESS_OR_EQUAL
                , Bytes.toBytes("2020-06-30"));

        // 3.2 构建过滤器列表
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL
                , startDateFilter
                , endDateFilter);

        scan.setFilter(filterList);

        // 4. 执行scan扫描请求
        ResultScanner resultScan = waterBillTable.getScanner(scan);

        // 5. 迭代打印result
        for (Result result : resultScan) {
            System.out.println("rowkey -> " + Bytes.toString(result.getRow()));
            System.out.println("------");

            List<Cell> cellList = result.listCells();

            // 6. 迭代单元格列表
            for (Cell cell : cellList) {
                // 打印列蔟名
                System.out.print(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
                System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));

            }
            System.out.println("------");
        }

        resultScan.close();


        // 7. 关闭表
        waterBillTable.close();
    }

解决中文乱码问题:

  • 前面我们的代码,在打印所有的列时,都是使用字符串打印的,Hbase中如果存储的是int、double,那么有可能就会乱码了。
    在这里插入图片描述

要解决的话,我们可以根据列来判断,使用哪种方式转换字节码。如下:

  1. NUM_CURRENT
  2. NUM_PREVIOUS
  3. NUM_USAGE
  4. TOTAL_MONEY

这4列使用double类型展示,其他的使用string类型展示

              if(colName.equals("NUM_CURRENT")
                        || colName.equals("NUM_PREVIOUS")
                        || colName.equals("NUM_USAGE")
                        || colName.equals("TOTAL_MONEY")) {
                    System.out.println(" => " + Bytes.toDouble(cell.getValueArray(), cell.getValueOffset()));
                }
                else {
                    System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
                }

在这里插入图片描述


HBase高可用

考虑关于HBase集群的一个问题,在当前的HBase集群中,只有一个Master,一旦Master出现故障,将会导致HBase不再可用。所以,在实际的生产环境中,是非常有必要搭建一个高可用的HBase集群的。

HBase高可用简介

  • HBase的高可用配置其实就是HMaster的高可用。要搭建HBase的高可用,只需要再选择一个节点作为HMaster,在HBase的conf目录下创建文件backup-masters,然后再backup-masters添加备份Master的记录。一条记录代表一个backup master,可以在文件配置多个记录。

搭建HBase高可用

  1. 在hbase的conf文件夹中创建 backup-masters 文件
cd /export/server/hbase-2.1.0/conf
touch backup-masters
  1. 将node2和node3添加到该文件中
vim backup-masters
node2
node3
  1. 将backup-masters文件分发到所有的服务器节点中
scp backup-masters node2:$PWD
scp backup-masters node3:$PWD
  1. 重新启动hbase
stop-hbase.sh
start-hbase.sh
  1. 查看webui,检查Backup Masters中是否有node2,node3
  • http://node1:16010/master-status

在这里插入图片描述

  1. 尝试杀掉node1节点上的master
kill -9 HMaster进程id
  1. 访问http://node2:16010和http://node3:16010,观察是否选举了新的Master

在这里插入图片描述

注意:

  • HBase的HA也是通过ZK来实现的(临时节点、watch机制)
  • 只需要添加一个backup-masters文件,往里面添加要称为Backup master的节点,HBase启动的时候,会自动启动多个HMaster
  • HBase配置了HA后,对Java代码没有影响。因为Java代码是通过从ZK中来获取Master的地址的

HBase架构

在这里插入图片描述

  • client:客户端,写的Java程序、hbase shell都是客户端(Flink、MapReduce、Spark)
  • Master Server
    • 监控RegionServer
    • 处理RegionServer故障转移
    • 处理元数据的变更
    • 处理region的分配或移除
    • 在空闲时间进行数据的负载均衡
    • 通过Zookeeper发布自己的位置给客户端

HMaster:主要是负责表的管理操作(创建表、删除表、Region分配),不负责具体的数据操作

  • Region Server
    • 处理分配给它的Region
    • 负责存储HBase的实际数据
    • 刷新缓存到HDFS
    • 维护HLog
    • 执行压缩
    • 负责处理Region分片
  • RegionServer中包含了大量丰富的组件,如下:
    • Write-Ahead logs
    • HFile(StoreFile)
    • Store
    • MemStore
    • Region

HRegionServer:负责数据的管理、数据的操作(增删改查)、负责接收客户端的请求来操作数据

在这里插入图片描述

  • Region
    • 在HBASE中,表被划分为很多「Region」,并由Region Server提供服务
      在这里插入图片描述

一个表由多个Region组成,每个Region保存一定的rowkey范围的数据,Region中的数据一定是有序的,是按照rowkey的字典序来排列的

  • Store
    • 存储的是表中每一个列蔟的数据
    • Region按列族垂直划分为「Store」,存储在HDFS在文件中
  • MemStore
    • MemStore与缓存内存类似
    • 当往HBase中写入数据时,首先是写入到MemStore
    • 每个列族将有一个MemStore
    • 当MemStore存储快满的时候,整个数据将写入到HDFS中的HFile中

所有的数据都是先写入到MemStore中,可以让读写操作更快,当MemStore快满的时候,需要有一个线程定期的将数据Flush到磁盘中

  • StoreFile
    • 每当任何数据被写入HBASE时,首先要写入MemStore
    • 当MemStore快满时,整个排序的key-value数据将被写入HDFS中的一个新的HFile中
    • 写入HFile的操作是连续的,速度非常快
    • 物理上存储的是HFile

HFile是在HDFS上保存的数据,是HBase独有的一种数据格式(丰富的结构、索引、DataBlock、BloomFilter布隆过滤器…)

  • WAL
    • WAL全称为Write Ahead Log,它最大的作用就是 故障恢复
    • WAL是HBase中提供的一种高并发、持久化的日志保存与回放机制
    • 每个业务数据的写入操作(PUT/DELETE/INCR),都会保存在WAL中
    • 一旦服务器崩溃,通过回放WAL,就可以实现恢复崩溃之前的数据
    • 物理上存储是Hadoop的Sequence File

WAL预写日志,当客户端连接RegionServer写数据的时候,会先写WAL预写日志,put/delete/incr命令写入到WAL,有点类似于之前Redis中的AOF,当某一个RegionServer出现故障时,还可以通过WAL来恢复数据,恢复的就是MemStore的数据。


常见Bug记录

  • Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
    • 找到$HADOOP_HOME/etc/mapred-site.xml,增加以下配置
    • 将配置文件分发到各个节点
    • 重新启动YARN集群
<property>
  <name>yarn.app.mapreduce.am.env</name>
  <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
  <name>mapreduce.map.env</name>
  <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
  <name>mapreduce.reduce.env</name>
  <value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
  • Caused by: java.net.ConnectException: Call to node2/192.168.88.101:16020 failed on connection exception: org.apache.hbase.thirdparty.io.netty.channel.ConnectTimeoutException: connection timed out: node2/192.168.88.101:16020
    • 无法连接到HBase,请检查HBase的Master是否正常启动
  • Starting namenodes on [localhost] ERROR: Attempting to launch hdfs namenode as root ,ERROR: but there is no HDFS_NAMENODE_USER defined. Aborting launch.
    • 解决办法: 是因为缺少用户定义造成的,所以分别编辑开始和关闭脚本
$ vim sbin/start-dfs.sh 
$ vim sbin/stop-dfs.sh 

在顶部空白处添加内容:

HDFS_DATANODE_USER=root 
HADOOP_SECURE_DN_USER=hdfs 
HDFS_NAMENODE_USER=root 
HDFS_SECONDARYNAMENODE_USER=root 
  • Starting resourcemanager ERROR: Attempting to launch yarn resourcemanager as root ERROR: but there is no YARN_RESOURCEMANAGER_USER defined. Aborting launch. Starting nodemanagers ERROR: Attempting to launch yarn nodemanager as root ERROR: but there is no YARN_NODEMANAGER_USER defined. Aborting launch
vim sbin/start-yarn.sh 
vim sbin/stop-yarn.sh 

YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
  • Exception in thread "main" java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$POSIX.stat
    • 将 hadoop.dll 放到c:/windows/system32文件夹中,重启IDEA,重新运行程序

本部分思维导图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/535834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊云科技使用Inf2实例运行GPT-J-6B模型

在2019年的亚马逊云科技re:Invent上&#xff0c;亚马逊云科技发布了Inferentia芯片和Inf1实例这两个基础设施。Inferentia是一种高性能机器学习推理芯片&#xff0c;由亚马逊云科技定制设计&#xff0c;其目的是提供具有成本效益的大规模低延迟预测。时隔四年&#xff0c;2023年…

生成bean的注解@Component极其衍生和@ComponentScan@Configuration

Component Spring 2.5 以后&#xff0c;除了提供基本的 Component 注解之外&#xff0c;还提供了 Service Controller Repository 三个注解。在 Spring 源码中&#xff0c;后面三个注解都在开始部分引入了 Component 注解&#xff0c;除此以外这四个注解的源码内容没有任何区别…

Json介绍

文章目录 1. 什么是 JSON&#xff1f;2. JSON语法格式3. JSON在Java中的用途3.1 FastJSON1. FastJSON概述与下载2. FastJSON常用方法 3.2. Jackson1. Jackson下载与使用2. Jackson常用类与方法3. ObjectMapper类常用方法 1. 什么是 JSON&#xff1f; JSON:JavaScript Object N…

C语言函数大全-- _w 开头的函数(2)

C语言函数大全 本篇介绍C语言函数大全-- _w 开头的函数 1. _wexecl 1.1 函数说明 函数声明函数功能int _wexecl(const wchar_t *path, const wchar_t *arg0, ... /* , const wchar_t *arg1, ..., NULL */);它是一个 Windows 平台下的 C 标准库函数&#xff0c;用于在新进程…

〖大学生·技术人必学的职业规划白宝书 - 职业规划篇②〗- 进入职场前必须要考虑的问题

历时18个月&#xff0c;采访 850 得到的需求。 不管你是在校大学生、研究生、还是在职的小伙伴&#xff0c;该专栏有你想要的职业规划、简历、面试的答案。说明&#xff1a;该文属于 大学生技术人职业规划白宝书 专栏&#xff0c;购买任意白宝书体系化专栏可加入TFS-CLUB 私域社…

leecode106——使用中序遍历和后序遍历构造一棵二叉树

leecode106 中序遍历和后序遍历构造一棵二叉树 &#x1f50e;中序遍历和后续遍历的性质 在后序遍历中&#xff0c;最后一个元素二叉树的根节点 在中序遍历序列中&#xff0c;根节点的左边为左子树&#xff0c;右边为右子树 &#x1f50e;1.二叉树的还原过程描述 1.首先&am…

HTTP协议基本格式

HTTP协议基本格式 TCP/IP的分层管理HTTP的基本格式 TCP/IP的分层管理 TCP/IP协议族里重要的一点就是分层。TCP/IP协议族按层次分别分为5层&#xff1a; 应用层、传输层、网络层、数据链路层、物理层。 TCP/IP层次化的好处。 如果互联网只由一个协议统筹&#xff0c;某个地方需…

不动点定理的及其有趣应用

最近读高观点下的数学这本书&#xff0c;对书中介绍的布劳威尔不动点定理的有趣性质印象很深&#xff0c;原因是这个定理的某些性质能够解释我们生活中的一些常见现象&#xff0c;这里结合一个例题&#xff0c;聊以记录。 从一个数学题讲起&#xff1a; f(x)是定义在[0,1]上的…

IPB60R099CP-ASEMI代理英飞凌高压MOS管IPB60R099CP

编辑&#xff1a;ll IPB60R099CP-ASEMI代理英飞凌高压MOS管IPB60R099CP 型号&#xff1a;IPB60R099CP 品牌&#xff1a;英飞凌 封装&#xff1a;TO-263 最大漏源电流&#xff1a;31A 漏源击穿电压&#xff1a;600V RDS&#xff08;ON&#xff09;Max&#xff1a;99mΩ …

【MySQL】MySQL百万数据深度分页优化思路分析

文章目录 一、业务背景二、瓶颈再现三、问题分析回表覆盖索引IOLIMTI 2000,10 &#xff1f; 四、问题总结五、解决方案优化前后性能对比 一、业务背景 一般在项目开发中会有很多的统计数据需要进行上报分析&#xff0c;一般在分析过后会在后台展示出来给运营和产品进行分页查看…

软考A计划-真题-分类精讲汇总-第十五章(数据库设计)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

如何做到乡村振兴?主要包括以下几点

乡村振兴是现代化发展的常记口号&#xff0c;也是中国整体经济发展的必备条件&#xff0c;乡村振兴是一个多元化的问题&#xff0c;其中包含人文、经济、文化、生态、人才等&#xff0c;那么如何做到乡村振兴呢&#xff1f; 主要包括以下几点&#xff1a; 1.合理利用土地资源…

SpringBoot配置文件敏感信息加密(四十六)

新的生活会开始&#xff0c;直到完成自己的目标. 一. 配置文件敏感信息加密 我们以前在编写 application.yml 文件时&#xff0c;服务器的ip, 数据库的配置&#xff0c;Redis的密码配置等都是明文&#xff0c;这是很不安全的。 我们可以通过 jasypt-spring-boot-starter 插件进…

Python学习26:个人所得税计算器

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 2018年10月1日以前&#xff…

Java 性能调优全攻略:步骤、工具、技巧一网打尽

Java性能调优是一项非常重要的工作&#xff0c;它可以提高应用程序的性能和可伸缩性&#xff0c;并确保应用程序在高负载情况下仍然能够快速、稳定地运行。 1、Java性能调优步骤 Java性能调优的主要步骤包括&#xff1a; 确定目标&#xff1a;首先需要明确性能调优的目标&…

提高数据的安全性和可控性,数栈基于 Ranger 实现的 Spark SQL 权限控制实践之路

在企业级应用中&#xff0c;数据的安全性和隐私保护是极其重要的。Spark 作为数栈底层计算引擎之一&#xff0c;必须确保数据只能被授权的人员访问&#xff0c;避免出现数据泄露和滥用的情况。为了实现Spark SQL 对数据的精细化管理及提高数据的安全性和可控性&#xff0c;数栈…

多维时序 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多变量时间序列预测

多维时序 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多变量时间序列预测 目录 多维时序 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多变量时间序列预测预测结果基本介绍模型特点程序设计学习总结参考资料 预测结果 基本介绍 多维时序 | MATLAB实现CN…

C++进阶——红黑树

C进阶——红黑树 概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过 对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出俩 倍&…

五分钟读完一本书 --《小王子》

所有的大人都曾经是小孩。 它是写给大人的童话。是一本用最简单纯净的文字&#xff0c;却将爱与羁绊描写得及其深刻的书。 看东西只有用心才能看得清楚&#xff0c;重要的东西用眼睛是看不见的。 这是踏遍7个星球之后 小王子才明白的道理。 小王子的B612星球小到只有一栋房子那…

小程序容器助力智能移动门户统一

智能移动统一门户遵循“统一规划&#xff0c;统一标准&#xff0c;统一建设&#xff0c;统一运维”的指导思想。它灵活运用前端展示平台&#xff0c;微服务后端平台&#xff0c;流程引擎&#xff0c;规则引擎&#xff0c;非结构化数据平台&#xff0c;即时通讯平台&#xff0c;…