当前位置: 代码网 > 科技>人工智能>数据分析 > HBase初识:很脆很能装

HBase初识:很脆很能装

2024年08月02日 数据分析 我要评论
HBase 的设计理念依据 Google 的 BigTable 论文,论文中对于数据模型的首句介绍。Bigtable 是一个稀疏的、分布式的、持久的多维排序map。之后对于映射的解释如下:“该映射由行键、列键和时间戳索引:映射中的每个值都是一个未解释的字节数组。最终HBase 关于数据模型和 BigTable 的对应关系如下:“HBase 使用与 Bigtable 非常相似的数据模型。用户将数据行存储在带标签的表中。数据行具有可排序的键和任意数量的列。

hbase数据模型

概述

hbase 的设计理念依据 google 的 bigtable 论文,论文中对于数据模型的首句介绍。
bigtable 是一个稀疏的、分布式的、持久的多维排序map。
之后对于映射的解释如下:“
该映射由行键、列键和时间戳索引:映射中的每个值都是一个未解释的字节数组。
最终hbase 关于数据模型和 bigtable 的对应关系如下:“
hbase 使用与 bigtable 非常相似的数据模型。用户将数据行存储在带标签的表中。数
据行具有可排序的键和任意数量的列。该表存储稀疏,因此如果用户喜欢,同一表中的行可
以具有疯狂变化的列。“
最终理解 hbase 数据模型的关键在于稀疏、分布式、多维、排序的映射。其中映射 map
指代非关系型数据库的 kev-value 结构。 

hbase是一个领先的 nosql 数据库
是一个面向列存储的 nosql 数据库
是一个分布式 h ash m ap,底层数据是 key-value 格式
基于google big table论文
使用hdfs作为存储并利用其可靠性
hbase 特点
数据访问速度快,响应时间约2-20毫秒
支持 随机读写 ,每个节点20k ~ 100k+ ops/s
可扩展性,可扩展到20,000 + 节点
高并发

hbase分布式环境部署

启动 zookeeper
启动hadoop( hdfs yarn
上传、解压、配置环境变量并修改配置文件
hbase-env.sh
hbase-site.xml
regionservers
启动测试
启动: start-hbase.sh

关闭:stop-hbase.sh

务必先关闭hbase  在关闭zookeeper

hbase的设计

物理架构

master
主要进程,具体实现类为hmaster,通常部署在namenode上
功能:负责通过zk监控recionserver进程状态,同时是所有元数据变化
的接口。内部启动监控执行region的故障转移和拆分的线程。
regionserver
主要进程,具体实现类为hregionserver,部署在datanode上
功能:主要负责数据cell的处理。同时在执行区域的拆分和合并的时候
 由regionserver来实际执行
(如配置高可用则存在backup)

hdfs集群存储表格数据hbase把表格的数据存储到hdfs上面,按照namespace- >table->region->store的格式划分文件夹存储。在store中存储hfile,内部为对应的cell。

master

  • 实现类为hmaster,负责监控集群中所有的 regionserver 实例。主要作用如下: 管理元数据表格 hbase:meta,接收用户对表格创建修改删除的命令并执行
  • 监控 region 是否需要进行负载均衡,故障转移和 region 的拆分。 通过启动多个后台线程监控实现上述功能: dloadbalancer 负载均衡器 周期性监控 region 分布在 regionserver 上面是否均衡,由参数 hbase.balancer.period 控制周期时间,默认5分钟。catalogjanitor 元数据管理器、 定期检查和清理hbase:meta中的数据

catalogjanitor元数据管理器的主要任务是确保这些元数据的准确性和一致性。它会定期检查.meta.表中的元数据,查找并清理可能存在的过期、无效或冗余的数据。这种清理过程对于保持hbase集群的健康运行至关重要,可以避免由于元数据不一致或错误导致的各种问题。

具体来说,catalogjanitor可能会清理的数据包括:

过期或孤立的元数据:当hbase中的表被删除或修改时,相关的元数据可能不再需要。catalogjanitor会识别并删除这些不再需要的元数据。

冗余的元数据:有时,由于各种原因(如系统错误、重复操作等),.meta.表中可能会出现重复的元数据。catalogjanitor会检测和删除这些冗余数据。

不一致的元数据:如果hbase集群中的元数据出现不一致的情况(例如,某个表的元数据在两个不同的region中都有记录),catalogjanitor会尝试修复或删除这些不一致的数据。

masterprocwal master 预写日志处理器 把master 需要执行的任务记录到预写日志 wal中,如果 master 宕机,让 backupmaster 读取日志继续干。

而meta就是专门用来存储和region相关的信息。

meat表内具体存放哪些信息: 
rowkey:由四个字段拼接起来,分别是 表名-stratrow-timestamp-encodedname。

数据分为4列:

  • info:regioninfo:encodedname、regionname、region的startrow、region的stoprow;
  • info:seqnumduringopen:存储region打开时的sequenceid;
  • info:server:存储region落在哪个regionserver上;
  • info:serverstartcode:存储所在的regionserver启动时间戳;

 region server 实现类为 hregionserver,主要作用如下:

  • 负责数据 cell 的处理,例如写入数据 put,查询数据get 等
  • 拆分并region的实际执行者,有 master 监控,有 regionserver 执行。
  • zookeeper hbase 通过 zookeeper 来做 master 的高可用、记录 regionserver 的部署信息、并且存储 有 meta 表的位置信息。“ hbase 对于数据的读写操作时直接访问 zokeeper 的,在2.3 版本推出master registry 模式,客户端可以直接访问 master。使用此功能,会加大对 master 的压力,减轻对 zookeeper的压力。

4) hdfs hdfs为hbase 提供最终的底层数据存储服务,同时为hbase 提供高容错的支持。

 

regiontable

region位于不同节点,而按照列族切分为store用于底层存储到不同的文件夹中,便于文件对应。

也就是说横着切  是为了存放不同节点,而竖着切是为了存放在同一节点的不同数据,比较列族可以无限扩张。

逻辑架构 - row

hbase 表中的每行数据都由一个 rowkey 和多个 column (列)组成,数据是按照rowkey的字典顺序存储的,并且查询数据时只能根据 rowkey 进行检索,所以rowkey 的设计十分重要。

hbase所有数据以字节方式存储,每行由以下五列组成

  • rowkey(行键) 行号
  • 列号  列族+列名 
  • 时间戳(标记版本)以便更新   使用唯一时间戳维护多个row版本
  • type put写入 delete 删除
  • value 数据值

hbase数据管理

数据管理目录
系统目录表hbase:meta
存储元数据
zookeeper 存储 hbase:meta表的位置信息
hbase 实际数据存储在 hdfs

 hbase应用场景示例

经过以上设计架构了解,可以理解以下场景hbase 的应用。

增量数据-时间序列数据
高容量,高速写入
hbase之上有opentsdb模块,可以满足时序类场景,比如传感器,系统监控,股票行情监控等

信息交换-消息传递
高容量,高速读写
通信、消息同步的应用构建在hbase之上,比如 email facebook
内容服务-web后端应用程序
高容量,高速读写
头条类、新闻类的的新闻、网页、图片存储在hbase中

 hbase的交互模式shell

[root@centos143 ~]# hbase shell
hbase(main):001:0> version         -- 查看当前hbase版本

hbase(main):002:0> list_namespace   -- 查看所有表空间

hbase(main):003:0> create_namespace 'xxy'  -- 创建表空间

-- 创建表
hbase(main):005:0> create 'xxy:student','baseinfo','schoolinfo'

--查看表详情
hbase(main):008:0> describe 'xxy:student'

启用/禁用
hbase(main):007:0> disable 'xxy:student'
hbase(main):011:0> enable 'xxy:student'
hbase(main):009:0> is_disabled 'xxy:student'
hbase(main):010:0> is_enabled 'xxy:student'

--删除表,必须将要删除的表先禁用
hbase(main):014:0> disable 'xxy:student'
hbase(main):014:0> drop 'xxy:student'

-- 删除表空间前必须将表空间中的所有表全部删除
hbase(main):020:0> drop_namespace 'xxy'

-- 显示指定表空间内所有的表    show tables;
hbase(main):024:0> list_namespace_tables 'xxy'

查看表是否存在
hbase(main):026:0> exists 'xxy:student'

--添加一个列簇
hbase(main):031:0> alter 'xxy:student','teacherinfo'

--删除列簇  teacherinfo
hbase(main):031:0> alter 'xxy:student',{name=>'teacherinfo',method=>'delete'}

--改变列簇版本限制
hbase(main):034:0> alter 'xxy:student',{name=>'baseinfo',versions=>3}

--插入数据
hbase(main):036:0> put 'xxy:student','rowkey1','baseinfo:name','tom'
took 0.0591 seconds                                                                                                   
hbase(main):037:0> put 'xxy:student','rowkey1','baseinfo:birthday','1990-01-09'
took 0.0046 seconds                                                                                                   
hbase(main):038:0> put 'xxy:student','rowkey1','baseinfo:age','34'
took 0.0081 seconds                                                                                                   
hbase(main):039:0> put 'xxy:student','rowkey1','schoolinfo:name','njyd'
took 0.0059 seconds                                                                                                   
hbase(main):040:0> put 'xxy:student','rowkey1','schoolinfo:address','nanjing'

-- get查询
hbase(main):041:0> get 'xxy:student','rowkey1'
查询指定表的指定列簇中的数据
hbase(main):042:0> get 'xxy:student','rowkey1','baseinfo'
hbase(main):043:0> get 'xxy:student','rowkey1','schoolinfo'
查询指定表中的指定列簇中的列
hbase(main):044:0> get 'xxy:student','rowkey1','schoolinfo:address'

hbase(main):045:0> put 'xxy:student','rowkey1','baseinfo:name','xxy'
hbase(main):047:0> put 'xxy:student','rowkey1','baseinfo:name','lijia'

查看历史版本数据,默认只保留当前版本
hbase(main):050:0> get 'xxy:student','rowkey1',{column=>'baseinfo:name',versions=>3}

java api

// get client admin

configuration config = hbaseconfiguration.create();
config.path("/opt/install/hbase/conf/hbase-site.xml");
config.path("/opt/install/hadoop/etc/hadoop/conf/core-site.xml");
connect= connectionfactory.createconnection(config);
admin =
connect.getadmin();

// 执行表操作

admin.createtable()

admin.disabletable()

admin.deletetable()

admin.listtable()

kafka 写入 hbase

附上一个java 将kafka清洗完的生产者数据写入  hbase  events_db:users表的实例

建表语句已在代码中注释

 


import org.apache.hadoop.conf.configuration;
import org.apache.hadoop.hbase.hbaseconfiguration;

import org.apache.hadoop.hbase.tablename;
import org.apache.hadoop.hbase.client.*;

import org.apache.kafka.clients.consumer.consumerconfig;
import org.apache.kafka.clients.consumer.consumerrecord;
import org.apache.kafka.clients.consumer.consumerrecords;
import org.apache.kafka.clients.consumer.kafkaconsumer;
import org.apache.kafka.common.serialization.stringdeserializer;

import java.io.ioexception;
import java.time.duration;
import java.util.arraylist;
import java.util.collections;
import java.util.properties;


public class userstohb { //38209
    static  long rownum=0;
    public static void main(string[] args) {
        properties prop = new properties();
        prop.put(consumerconfig.bootstrap_servers_config, "192.168.78.143:9092");
        prop.put(consumerconfig.key_deserializer_class_config, stringdeserializer.class);
        prop.put(consumerconfig.value_deserializer_class_config, stringdeserializer.class);

        // 设置是否自动提交, false 手动提交,  true 自动提交
        prop.put(consumerconfig.enable_auto_commit_config, "false");
        prop.put(consumerconfig.auto_commit_interval_ms_config, "500");
        prop.put(consumerconfig.auto_offset_reset_config, "earliest");

//        配置消费者组
        prop.put(consumerconfig.group_id_config, "users_group1");
        kafkaconsumer<string, string> consumer = new kafkaconsumer<string, string>(prop);
        consumer.subscribe(collections.singleton("users")); //取


        //hbase
        configuration conf = hbaseconfiguration.create();
        conf.set("hbase.zookeeper.quorum", "192.168.78.143");
        conf.set("hbase.zookeeper.property.clientport", "2181");
        conf.set("hbase.roodir", "hdfs://192.168.78.143:9000/hbase");
        connection conn = null;
        try {
            conn = connectionfactory.createconnection(conf);
//            table table = conn.gettable(tablename.valueof("bigdata:teacher"));
            tablename tablename = tablename.valueof("events_db:users");
            final bufferedmutator.exceptionlistener listener = new bufferedmutator.exceptionlistener() {

                public void onexception(retriesexhaustedwithdetailsexception exception, bufferedmutator mutator) throws retriesexhaustedwithdetailsexception {//监听失败
                    int nums = exception.getnumexceptions();
                    for (int i = 0; i < nums; i++) {
                        system.err.println("失败 保存" + exception.getrow(i) + ".");
                    }
                }
            };
            bufferedmutatorparams parms = new bufferedmutatorparams(tablename);
            parms.writebuffersize(1024 * 1024);
            parms.listener(listener);
            parms.setwritebufferperiodicflushtimeoutms(2 * 1000);//2s 刷一次

            bufferedmutator mutator = conn.getbufferedmutator(parms);
            arraylist<put> list = new arraylist<>();
            while (true) {
                list.clear();
                consumerrecords<string, string> poll =
                        consumer.poll(duration.ofmillis(100));
                for (consumerrecord<string, string> record : poll) {
                    rownum++;
                    string[] user = record.value().split(",");
                    put put = new put(user[0].getbytes());
//                    create 'events_db:users', 'profile', 'region', 'registration'
//                    create 'events_db:user_friend', 'uf'
//                    create 'events_db:events', 'schedule', 'location', 'creator', 'remark'
//                    create 'events_db:event_attendee', 'euat'
//                    create 'events_db:train', 'eu'
                    put.addcolumn("region".getbytes(),"locale".getbytes(),user[1].getbytes());
                    put.addcolumn("profile".getbytes(),"birthday".getbytes(),user[2].getbytes());
                    put.addcolumn("profile".getbytes(),"gender".getbytes(),user[3].getbytes());
                    if(user.length>4){
                        put.addcolumn("registration".getbytes(),"joinat".getbytes(),user[4].getbytes());
                    }
                    if(user.length>5){
                        put.addcolumn("region".getbytes(),"location".getbytes(),user[5].getbytes());
                    }
                    if(user.length>6){
                        put.addcolumn("region".getbytes(),"timezone".getbytes(),user[6].getbytes());
                    }
                    list.add(put);
                  
                }
                if(list.size()>0)
                mutator.mutate(list);
            }
            //thread.sleep(1000);
            
        } catch (ioexception e) {
            throw new runtimeexception(e);
        }


    }
}

scan表中数据如下

为什么说hbase很脆呢,因为笔者在学习过程中真的玩坏了很多次,请每次学习结束后务必关闭hbase后再挂起(先关闭啥再关啥想清楚),其他东西不一定坏,hbase是真的脆

尝试用线程池 向hbase 写入模拟的几百万条数据 写崩过好几次,后来乖乖单线程 慢慢等。

坏了之后修需 删掉hbase 跟 zookeeper cli底下的相关文件,当然表数据自然全无。

还请细心照料!!!、

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com