利用多线程批Put方式压测HBase

2023-11-04

利用多线程批Put方式压测HBase

背景

在正式上生产之前,一定要对集群的组件做稳定性和性能压测,这是常识。这种压测当然不能指望那些只会鼠标点几下网页并经常指责前端页面样式有bug的测试去做。。。这种稍微有点技术含量的事情,她们其实有心无力。。。

众所周知,表的列用百万为基本单位,行号用10亿为基本单位计数时,才配得上用HBase。。。所以HBase的实际应用场景大部分是大宽表【SQL Boy们手写SQL的那种几百个字段的Hive表叫宽表没啥问题,但是不够资格叫大宽表】。做性能压测绝对不能只用几十个字段或者几百w行数据,这种RDBMS都能轻松应付的场景不配用HBase。。。要做稳定性压测,一定是以压爆HBase集群为目的的,正式上线前压爆了去做一些jvm调优,总比上了生产环境天天爆库强一点。。。

当然有时候不一定是为了压爆集群,还可能是对HBase的协处理器做一些技术调研,例如:RSGroup硬件级资源隔离。这种情况更多是观察在大数据量场景下,协处理器是否会出错。

Demo

上一个简单的Demo。读者可以参照着改参数适应自己公司的场景。

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>zhiyong_study</artifactId>
        <groupId>com.zhiyong</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hbase_study</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <hbase-client.version>2.1.10</hbase-client.version>
        <hbase.version>2.1.10</hbase.version>
        <hbase-common.version>2.1.10</hbase-common.version>
        <hbase-server.version>2.1.10</hbase-server.version>
        <lombok-version>1.18.24</lombok-version>
        <encoding>UTF-8</encoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>${hbase-client.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish</groupId>
                    <artifactId>javax.el</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

<!--        损坏-->
<!--        <dependency>-->
<!--            <groupId>org.apache.hbase</groupId>-->
<!--            <artifactId>hbase</artifactId>-->
<!--            <version>${hbase.version}</version>-->
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>org.glassfish</groupId>-->
<!--                    <artifactId>javax.el</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-common</artifactId>
            <version>${hbase-common.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish</groupId>
                    <artifactId>javax.el</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>${hbase-server.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish</groupId>
                    <artifactId>javax.el</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>



    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

需要排除org.glassfish的依赖,否则HBase的Maven依赖会爆红!!!如果公司用的是CDP,当然要改成服务器的组件对应的版本!!!

Java

采用多线程的方式,一个Jar包就可以模拟出所需的并发。当网络的带宽不够时,还是需要多个node上同时启动来减少网络的影响。

package com.zhiyong;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.security.UserGroupInformation;

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.UUID;

/**
 * @program: zhiyong_study
 * @description: HBase的put压力测试
 * @author: zhiyong
 * @create: 2023-04-02 20:29
 **/
public class HBasePutPressTest implements Runnable{
    private Thread thread;

    @Override
    public void run() {
        long timeStart = System.currentTimeMillis();//开始时间
        long timeEnd = 0;
        org.apache.hadoop.hbase.client.Connection connection = null;
        Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.quorum", "192.168.88.101:2181,192.168.88.102:2181,192.168.88.103:2181");
        configuration.set("zookeeper.znode.parent", "/hbase");
        configuration.set("hbase.client.retries.number", "3");
        configuration.set("hbase.security.authentication", "kerberos");
        configuration.set("keytab.file", "D:/krb/zhiyong.keytab");//Win路径
//        configuration.set("keytab.file","/krb/zhiyong.keytab");//Linux路径
        configuration.set("kerberos.principal", "zhiyong");
        configuration.set("hbase.master.kerberos.principal", "hbase/_HOST@ZHIYONG.COM");
        configuration.set("hbase.regionserver.kerberos.principal", "hbase/_HOST@ZHIYONG.COM");
        configuration.set("hadoop.security.authentication", "kerberos");
        System.setProperty("java.security.krb5.conf", "D:/krb/krb5.conf");//Win路径
//        System.setProperty("java.security.krb5.conf","/krb/krb5.conf");//Linux路径

        UserGroupInformation.setConfiguration(configuration);

        try {
            UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("zhiyong", "D:/krb/zhiyong.keytab");//Win路径
//          UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("zhiyong","/krb/zhiyong.keytab");//Linux路径
            UserGroupInformation.setLoginUser(ugi);
            System.out.println("Kerberos->HBase认证成功");

        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            HBaseAdmin.available(configuration);
            connection = ConnectionFactory.createConnection(configuration);

            timeEnd = System.currentTimeMillis();
            System.out.println("构建connection成功");
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("构建connection耗时:" + (timeEnd - timeStart) + "ms");

        Table table = null;


        try {
            table = connection.getTable(TableName.valueOf("db_lzy:tb1"));
            System.out.println("获取到HBase表:db_lzy:tb1");
        } catch (Exception e) {
            e.printStackTrace();
        }

        String rowkey = "";
        StringBuilder strb = new StringBuilder();
        Long rowCounter = 0L;
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        //一次put10000列
        for (int i = 0; i < 10000; i++) {
            map.put("col" + i, UUID.randomUUID().toString() + UUID.randomUUID().toString() + UUID.randomUUID().toString());
        }

        //批put
        for (int i = 0; i < 100000; i++) {
            LinkedList<Put> puts = new LinkedList<>();

            for (int j = 0; j < 1000; j++) {
                strb.delete(0, strb.length());
                strb.append(String.valueOf(System.currentTimeMillis()));
                strb.reverse();
                rowkey = strb.toString();
                strb.delete(0, strb.length());
                Put put = new Put(rowkey.getBytes());

                for (String col : map.keySet()) {
                    put.addColumn("f1".getBytes(), col.getBytes(), map.get(col).toString().getBytes());
                }

                puts.add(put);
            }

            try {
                table.put(puts);
                rowCounter++;
                System.out.println("插入第" + rowCounter + "批次成功");
            } catch (Exception e) {
                e.printStackTrace();
            }


        }

        System.out.println("插入批次数:" + rowCounter);

        try {
            table.close();
        } catch (Exception e){
            System.out.println("关闭Table失败");
        }
    }

    public void start(){
        if (null==thread){
            thread=new Thread();
            thread.start();
        }
    }

    public static void main(String[] args) {
        System.out.println("启动");
        int threadCounter = 20;

        for (int i = 0; i < threadCounter; i++) {
            HBasePutPressTest test = new HBasePutPressTest();
            test.start();
        }

    }
}

过Kerberos认证的模式会比较麻烦,如果没有Kerberos认证,会简单不少。

大体上就是反转时间戳做rowkey,防止出现数据热点。每条数据1个列族,10000个列,每10000条数据做一个Batch put批处理,这是我们的生产环境常用的方式。一般很少有单条put的情况,这样玩容易让HBase频繁GC进而OOM或者别的问题宕掉,这是严厉禁止的做法。

笔者这里是受限于网络带宽不足的问题,20线程并发,实际还是要多台node并行跑这个Jar包。

结果

以当时的压测结果来看,RSGroup配置好后,HBase可以把大批量数据正确地存到指定分组的Region Server中,没有出现差错。期间压爆了几个node,但是整体对外服务依旧可用。最终挂服务器跑了一天多,把集群的HDFS接近写满的时候,由于HDFS先抗不住压力挂掉了,才把整个HBase集群压爆了!

至于RSGroup硬件级资源隔离,是另一个故事了。

转载请注明出处:https://lizhiyong.blog.csdn.net/article/details/129918165
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

利用多线程批Put方式压测HBase 的相关文章

  • XSD 验证错误:在 web.xml 中找不到 TagLib 标记

    我详细显示错误如下 cvc complex type 2 4 a 发现以元素开头的无效内容 taglib One of http java sun com xml ns javaee 描述 http java sun com xml ns
  • 使用缩略图器,我可以制作具有相同高度和宽度的缩略图,无论图像大小如何

    In 缩略图器 http code google com p thumbnailator 我正在制作缩略图 如果图像大小是 400 300 并且如果我执行以下操作 Thumbnails of new File original jpg si
  • Emacs 打字骨架对插入也许

    在 Eclipse 中 编辑 Java 代码时 如果我输入一个左括号 我会得到一对括号 如果我然后 输入 第二个括号 它不会插入额外的括号 我如何在 emacs 中得到它 Eclipse 编辑器足够聪明 当我输入闭括号时 它知道我刚刚完成了
  • 如何实现 Eclipse 清理和构建(又名重建)?

    我删除了我的 binEclipse Indigo 中的文件夹 与 Helios 非常相似 现在我想知道如何重建我的 Java 项目 我只是找不到像 Netbeans 中那样的按钮 对于 Eclipse 您可以在下面找到重建选项项目 gt 清
  • 什么是“非阻塞”并发?它与普通并发有何不同?

    什么是 非阻塞 并发 它与使用线程的普通并发有何不同 为什么不在所有需要并发的场景中都使用非阻塞并发呢 使用非阻塞并发有开销吗 我听说Java中可以实现非阻塞并发 我们是否应该在特定场景下使用此功能 将这些方法之一与集合一起使用是否有区别或
  • 如何制作具有两个索引的 Map?

    我在java中有一张这样的地图 Map
  • Junit测试中LocalDateTime反序列化的问题

    我有问题LocalDateTime反序列化Junit测试 我有简单的REST API返回一些DTO目的 当我呼叫端点时 响应没有问题 它是正确的 然后我尝试编写单元测试 得到MvcResult并使用ObjectMapper将其转换为我的DT
  • 将 Java 3D 坐标转换为 2D 屏幕坐标

    我正在使用一个名为 Walrus 的 Java 3D 应用程序 该应用程序用于显示有向图 该代码已经具有突出显示节点并在给定其屏幕坐标的情况下在图形中相邻绘制标签的功能 旋转屏幕后 该节点不再突出显示 我所拥有的是 3D 中的节点坐标 我需
  • 从多个地方绘制 JPanel

    我目前正在为学校开发一款 Java 2D 游戏 我们必须使用抽象工厂设计模式 对于 2D 实现 我使用工厂如下 public class Java2DFact extends AbstractFactory public Display d
  • 在类路径中使用通配符调用 java 失败

    我当前目录中有一些 jar 它们都需要位于类路径中 因此我想对类路径使用通配符约定 命令行是 java exe classpath org python util jython args 但是我收到这个错误 Exception in thr
  • 如何使用 Tomcat 启用浏览器缓存静态内容(图像、css、js)?

    如何使用 Tomcat 启用浏览器缓存静态内容 图像 css js 首选的解决方案是编辑 spring MVC 配置文件或 web xml 尝试 改变值
  • 使用枚举变量切换字符串

    我有一个具有不同值的枚举 并且想要切换字符串变量 现在 我在尝试将枚举值转换为字符串 可以用作大小写常量 时遇到了困难 我最好的尝试是将枚举转换为字符串数组 但开关似乎不接受数组值作为大小写常量 IntelliJ 说 需要恒定的表达 Enu
  • 公共领域有哪些替代方案?

    我正在用 java 编写一个游戏 正如问题标题建议的那样 我在类中使用公共字段 暂且 据我所知 公共领域很糟糕 我有一些理解其中的原因 但如果有人能澄清为什么你不应该使用它们 那将不胜感激 问题是 从我所看到的来看 这似乎是合乎逻辑的 是使
  • Java文本输出中的UTF-8编码问题

    我一直致力于测试高棉语 Unicode Wordbreaker 的各种解决方案 高棉语单词之间没有空格 这使得拼写检查和语法检查变得困难 以及从旧高棉语转换为高棉语 Unicode 我得到了一些源代码 现在在线 http www white
  • 如何将空字符串序列化为单个空标签?

    我使用 Simple XML 框架序列化此类 Root public class HowToRenderEmptyTag Element required false private String nullString 我想得到
  • 使用 JPA 存储库保留 Spring Batch ItemWriter 的问题

    我对春季批次有疑问ItemWriter它依赖于 JPA 存储库来更新数据 这里是 Component public class MessagesDigestMailerItemWriter implements ItemWriter
  • 从 Brixton.RC1 开始的 ZuulProxy 未传递授权标头

    从 Spring Cloud 切换时Brixton M5 to Brixton RC1我的 ZuulProxy 不再通过Authorization标头下游到我的代理服务 我的设置中有各种各样的角色 但大多数都相当简单 Authorizati
  • 如何找到 JAR:/home/hadoop/contrib/streaming/hadoop-streaming.jar

    我正在练习有关 Amazon EMR 的复数视角视频教程 我被困住了 因为我收到此错误而无法继续 Not a valid JAR home hadoop contrib streaming hadoop streaming jar 请注意
  • 启动 Firefox 并等待其关闭

    Question 我想启动 Firefox 网络浏览器作为访问特定网站的过程 然后等到它关闭 一种特殊情况是浏览器可能已经打开并正在运行 因为用户可能已经访问过某个网站 在这种情况下 浏览器可能会在现有窗口中打开一个新选项卡 并且新启动的进
  • 只有创建视图层次结构的原始线程才能触摸其视图。在安卓上[重复]

    这个问题在这里已经有答案了 我只是一个初学者 所以请原谅我问一个可能愚蠢的问题 我不明白只有创建视图层次结构的原始线程才能触摸其视图的含义 请有人告诉我为什么会发生此错误以及如何解决此问题 ThankYou 这是我的班级 public cl

随机推荐

  • Tarjan 强连通分量算法的 Java 实现

    强连通分量算法是图论中的一个重要算法 用于将有向图分解为若干个强连通分量 Tarjan 算法是其中一种常用的实现方式 它可以高效地找到图中的所有强连通分量 本文将介绍 Tarjan 强连通分量算法的 Java 实现 并提供相应的源代码 首先
  • 万用表的使用

    deprecate 反对 轻视 declaration 宣告 声明书 宣布 宣告 申报 arg argue 争论 论证 争辩 主张 认为 提供证据 证明 表明 原因等 type 类型 种类 打字 成为 的典型 function 功能 作用
  • [721]linux安装kafka及命令行使用

    文章目录 一 安装kafka 二 解压kafka 三 修改server properties文件 四 修改zookeeper properties文件 五 添加kafka启动脚本 六 启动kafka 七 命令行使用kafka 创建topic
  • Vue知识系列(4)每天10个小知识点

    目录 系列文章目录 Vue知识系列 1 每天10个小知识点 Vue知识系列 2 每天10个小知识点 Vue知识系列 3 每天10个小知识点 知识点 31 Vuex 四种属性的概念 作用 使用示例 32 Vuex 和单纯的全局对象 的概念 作
  • Linux磁盘分区和文件系统的关系

    一 Linux磁盘相关命令及作用 1 df命令 用于显示文件系统的磁盘空间使用情况 2 du命令 用于查看文件或目录的磁盘使用情况 3 fdisk命令 用于磁盘分区表的创建和管理 4 mkfs命令 用于创建文件系统 5 mount命令 用于
  • 华北电力计算机专业排名,华电考研计算机专业排名

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1354计算机软件与理论359 1355计算机软件与理论340 1356计算机软件与理论334 1357计算机软件与理论329 1358计算机软件与理论326 1359计算机软件与理论324 1
  • C++/C++11中引用的使用

    引用 reference 是一种复合类型 compound type 引用为对象起了另外一个名字 引用类型引用 refer to 另外一种类型 通过将声明符写成 d的形式来定义引用类型 其中d是声明的变量名 一 一般引用 一般在初始化变量时
  • Cocos2dx on Qt

    讨论贴在这里 http www cocos2d x org boards 6 topics 8043 page 1 准备 glew 库 bin glew32 dll gt windows system32 include GL gt VC
  • STM32F103时钟配置流程

    知识点 系统复位后 HSI振荡器被选为系统时钟 当时钟源被直接或通过PLL间接作为系统时钟时 它将不能被停止 STM32F103的三个可以作为系统时钟的时钟源 分别是HSI HSE PLL 而PLL的时钟源是HSI 2 内部RC振荡器二分频
  • 华硕计算机cpu怎么超频怎么设置,内存和CPU超频操作_华硕 ROG Rampage VI Apex_主板评测-中关村在线...

    进阶操作 进BIOS可能很多人都是为了去给CPU和内存进行超频 首先按F7进入到高级模式 华硕的主板选择Extreme Tweaker选项卡 有的主板是AI Tweaker或者超频设置等名字 Extreme Tweaker选项卡 内存超频
  • 如何使用postman做接口测试

    常用的接口测试工具主要有以下几种 Postman 简单方便的接口调试工具 便于分享和协作 具有接口调试 接口集管理 环境配置 参数化 断言 批量执行 录制接口 Mock Server 接口文档 接口监控等功能 JMeter 开源接口测试及压
  • Python中is和==(is not和!=)的区别

    Python中有很多种运算符 本文主要记录一下is和 这两种运算符的区别 id 函数是查看该对象所在内存地址 每个对象都有对应的内存地址 如 is 用于判断两个变量引用对象是否为同一个 用于判断引用变量的值是否相等 类似于Java中的equ
  • 华为OD机试 - 按单词下标区间翻转文章内容(Java)

    题目描述 给定一段英文文章片段 由若干单词组成 单词间以空格间隔 单词下标从0开始 请翻转片段中指定区间的单词顺序并返回翻转后的内容 例如给定的英文文章片段为 I am a developer 翻转区间为 0 3 则输出 developer
  • HJ26 字符串排序

    Powered by NEFU AB IN Link 文章目录 HJ26 字符串排序 题意 思路 代码 HJ26 字符串排序 题意 编写一个程序 将输入字符串中的字符按如下规则排序 规则 1 英文字母从 A 到 Z 排列 不区分大小写 如
  • PCL 计算点云法向量并显示

    目录 一 算法原理 1 法向量估计 2 法向量定向 3 表面曲率 4 参考文献 5 法向量定向的理解 6 CloudCompare 二 pcl Normal的定义 三 pcl Normal的几种输出方式 四 计算法线并显示 1 计算输入点云
  • 单点登录(简单的实现)

    假设现在有两个域名 分别为 分别记为client1 client2 client1 com client2 com 一个认证服务器 域名 ssoserver com client1 client2都需要登陆后才能访问到数据 现在想要实现cl
  • 76-C语言-输入班级学生的姓名和三科成绩,按总分排名

    问题 输入50分学生的姓名和三科成绩 按降序输出名字和总分 成绩相同的并列排名 思路 因为要学生排名 且一个学生有姓名 成绩 以及总分 所以弄一个学生的结构体 有多少学生 就输入该结构体的数组 一个for循环 给每个学生赋值 排序 降序 用
  • 【c++中的细节问题】关于typedef的详细用法

    请见 C C typedef用法详解 真的很详细 superhoy的专栏 CSDN博客 c typedef
  • 3.Linux文件管理和 I/O 重定向

    Linux文件管理和 I O 重定向 Linux文件系统目录结构 常见目录说明 根目录 一般根目录下只存放目录 在Linux下有且只有一个根目录 所有的东西都是从这里开始 当你在终端里输入 home 你其实是在告诉电脑 先从 根目录 开始
  • 利用多线程批Put方式压测HBase

    利用多线程批Put方式压测HBase 背景 在正式上生产之前 一定要对集群的组件做稳定性和性能压测 这是常识 这种压测当然不能指望那些只会鼠标点几下网页并经常指责前端页面样式有bug的测试去做 这种稍微有点技术含量的事情 她们其实有心无力