日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

/opt/hbase/conf 中不能启动hbase_Hbase从入门到入坑

發(fā)布時(shí)間:2023/12/31 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 /opt/hbase/conf 中不能启动hbase_Hbase从入门到入坑 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 什么是HBASE

HBASE是一個(gè)高可靠性、高性能、面向列、可伸縮的分布式存儲(chǔ)系統(tǒng),利用HBASE技術(shù)可在廉價(jià)PC Server上搭建起大規(guī)模結(jié)構(gòu)化存儲(chǔ)集群。

HBASE的目標(biāo)是存儲(chǔ)并處理大型的數(shù)據(jù),更具體來說是僅需使用普通的硬件配置,就能夠處理由成千上萬(wàn)的行和列所組成的大型數(shù)據(jù)。

HBASE是Google Bigtable的開源實(shí)現(xiàn),但是也有很多不同之處。比如:Google Bigtable利用GFS作為其文件存儲(chǔ)系統(tǒng),HBASE利用Hadoop HDFS作為其文件存儲(chǔ)系統(tǒng);Google運(yùn)行MAPREDUCE來處理Bigtable中的海量數(shù)據(jù),HBASE同樣利用Hadoop MapReduce來處理HBASE中的海量數(shù)據(jù);Google Bigtable利用Chubby作為協(xié)同服務(wù),HBASE利用Zookeeper作為對(duì)應(yīng)。

HBASE與mysql、oralce、db2、sqlserver等關(guān)系型數(shù)據(jù)庫(kù)不同,它是一個(gè)NoSQL數(shù)據(jù)庫(kù)(非關(guān)系型數(shù)據(jù)庫(kù))

  • Hbase的表模型與關(guān)系型數(shù)據(jù)庫(kù)的表模型不同:
  • Hbase的表沒有固定的字段定義;
  • Hbase的表中每行存儲(chǔ)的都是一些key-value對(duì)
  • Hbase的表中有列族的劃分,用戶可以指定將哪些kv插入哪個(gè)列族
  • Hbase的表在物理存儲(chǔ)上,是按照列族來分割的,不同列族的數(shù)據(jù)一定存儲(chǔ)在不同的文件中
  • Hbase的表中的每一行都固定有一個(gè)行鍵,而且每一行的行鍵在表中不能重復(fù)
  • Hbase中的數(shù)據(jù),包含行鍵,包含key,包含value,都是byte[ ]類型,hbase不負(fù)責(zé)為用戶維護(hù)數(shù)據(jù)類型
  • HBASE對(duì)事務(wù)的支持很差
  • HBASE相比于其他nosql數(shù)據(jù)庫(kù)(mongodb、redis、cassendra、hazelcast)的特點(diǎn):

    Hbase的表數(shù)據(jù)存儲(chǔ)在HDFS文件系統(tǒng)中

    從而,hbase具備如下特性:

    • 存儲(chǔ)容量可以線性擴(kuò)展;
    • 數(shù)據(jù)存儲(chǔ)的安全性可靠性極高!

    二 安裝HBASE

    HBASE是一個(gè)分布式系統(tǒng)

    其中有一個(gè)管理角色:HMaster(一般2臺(tái),一臺(tái)active,一臺(tái)backup)

    其他的數(shù)據(jù)節(jié)點(diǎn)角色:HRegionServer(很多臺(tái),看數(shù)據(jù)容量)

    2.1 安裝準(zhǔn)備

    需要先有一個(gè)java環(huán)境

    首先,要有一個(gè)HDFS集群,并正常運(yùn)行;regionserver應(yīng)該跟hdfs中的datanode在一起

    其次,還需要一個(gè)zookeeper集群,并正常運(yùn)行

    然后,安裝HBASE

    角色分配如下:

    Hdp01: namenode datanode regionserver hmaster zookeeper

    Hdp02: datanode regionserver zookeeper

    Hdp03: datanode regionserver zookeeper

    2.2 安裝步驟

    解壓hbase安裝包

    修改hbase-env.sh

    export JAVA_HOME=/root/apps/jdk1.7.0_67

    export HBASE_MANAGES_ZK=false

    修改hbase-site.xml

    hbase.rootdir

    hdfs://hdp01:9000/hbase

    hbase.cluster.distributed

    true

    hbase.zookeeper.quorum

    hdp01:2181,hdp02:2181,hdp03:2181

    修改 regionservers

    hdp01

    hdp02

    hdp03

    2.3 啟動(dòng)hbase集群

    bin/start-hbase.sh

    啟動(dòng)完后,還可以在集群中找任意一臺(tái)機(jī)器啟動(dòng)一個(gè)備用的master

    bin/hbase-daemon.sh start master

    新啟的這個(gè)master會(huì)處于backup狀態(tài)

    三 hbase初體驗(yàn)

    3.1 啟動(dòng)hbase命令行客戶端

    bin/hbase?shellHbase>?list?????//?查看表Hbase>?status???//?查看集群狀態(tài)Hbase> version // 查看集群版本

    3.2 hbase表模型的特點(diǎn)

  • 一個(gè)表,有表名
  • 一個(gè)表可以分為多個(gè)列族(不同列族的數(shù)據(jù)會(huì)存儲(chǔ)在不同文件中)
  • 表中的每一行有一個(gè)“行鍵rowkey”,而且行鍵在表中不能重復(fù)
  • 表中的每一對(duì)kv數(shù)據(jù)稱作一個(gè)cell
  • hbase可以對(duì)數(shù)據(jù)存儲(chǔ)多個(gè)歷史版本(歷史版本數(shù)量可配置)
  • 整張表由于數(shù)據(jù)量過大,會(huì)被橫向切分成若干個(gè)region(用rowkey范圍標(biāo)識(shí)),不同region的數(shù)據(jù)也存儲(chǔ)在不同文件中
  • hbase會(huì)對(duì)插入的數(shù)據(jù)按順序存儲(chǔ):
  • 要點(diǎn)一:首先會(huì)按行鍵排序

    要點(diǎn)二:同一行里面的kv會(huì)按列族排序,再按k排序

    3.3 hbase的表中能存儲(chǔ)什么數(shù)據(jù)類型

    hbase中只支持byte[]

    此處的byte[] 包括了:rowkey,key,value,列族名,表名

    3.4 hbase命令行客戶端操作

    名稱

    命令表達(dá)式

    創(chuàng)建表

    create '表名', '列族名1','列族名2','列族名N'

    查看所有表

    list

    描述表

    describe ‘表名’

    判斷表存在

    exists '表名'

    判斷是否禁用啟用表

    is_enabled '表名'

    is_disabled ‘表名’

    添加記錄

    put ‘表名’, ‘rowKey’, ‘列族 : 列‘ , '值'

    查看記錄rowkey下的所有數(shù)據(jù)

    get '表名' , 'rowKey'

    查看表中的記錄總數(shù)

    count '表名'

    獲取某個(gè)列族

    get '表名','rowkey','列族'

    獲取某個(gè)列族的某個(gè)列

    get '表名','rowkey','列族:列’

    刪除記錄

    delete ‘表名’ ,‘行名’ , ‘列族:列'

    刪除整行

    deleteall '表名','rowkey'

    刪除一張表

    先要屏蔽該表,才能對(duì)該表進(jìn)行刪除

    第一步 disable ‘表名’ ,第二步 drop '表名'

    清空表

    truncate '表名'

    查看所有記錄

    scan "表名"

    查看某個(gè)表某個(gè)列中所有數(shù)據(jù)

    scan "表名" , {COLUMNS=>'列族名:列名'}

    更新記錄

    就是重寫一遍,進(jìn)行覆蓋,hbase沒有修改,都是追加

    3.4.1 建表

    create?'t_user_info','base_info','extra_info' 表名 列族名 列族名

    3.4.2 插入數(shù)據(jù)

    hbase(main):011:0> put 't_user_info','001','base_info:username','zhangsan'0 row(s) in 0.2420 seconds?hbase(main):012:0> put 't_user_info','001','base_info:age','18'0 row(s) in 0.0140 seconds?hbase(main):013:0> put 't_user_info','001','base_info:sex','female'0?row(s)?in?0.0070?seconds?hbase(main):014:0> put 't_user_info','001','extra_info:career','it'0 row(s) in 0.0090 seconds?hbase(main):015:0> put 't_user_info','002','extra_info:career','actoress'0?row(s)?in?0.0090?seconds?hbase(main):016:0> put 't_user_info','002','base_info:username','liuyifei'0 row(s) in 0.0060 seconds

    3.4.3 查詢方式一 scan掃描

    hbase(main):017:0> scan 't_user_info'ROW COLUMN+CELL 001 column=base_info:age, timestamp=1496567924507, value=18 001 column=base_info:sex, timestamp=1496567934669, value=female 001 column=base_info:username, timestamp=1496567889554, value=zhangsan 001 column=extra_info:career, timestamp=1496567963992, value=it 002 column=base_info:username, timestamp=1496568034187, value=liuyifei 002 column=extra_info:career, timestamp=1496568008631, value=actoress?

    3.4.4 查詢方式二 get單行數(shù)據(jù)

    hbase(main):020:0> get 't_user_info','001'COLUMN CELL base_info:age timestamp=1496568160192, value=19 base_info:sex timestamp=1496567934669, value=female base_info:username timestamp=1496567889554, value=zhangsan extra_info:career timestamp=1496567963992, value=it 4 row(s) in 0.0770 seconds

    3.4.5 刪除一個(gè)kv數(shù)據(jù)

    hbase(main):021:0> delete 't_user_info','001','base_info:sex'0 row(s) in 0.0390 seconds

    刪除整行數(shù)據(jù)

    hbase(main):024:0> deleteall 't_user_info','001'0 row(s) in 0.0090 secondshbase(main):025:0> get 't_user_info','001'COLUMN CELL 0 row(s) in 0.0110 seconds

    3.4.6 刪除整個(gè)表

    hbase(main):028:0> disable 't_user_info'0 row(s) in 2.3640 secondshbase(main):029:0> drop 't_user_info'0 row(s) in 1.2950 secondshbase(main):030:0> listTABLE 0 row(s) in 0.0130 seconds=> []

    3.5 Hbase重要特性-排序特性(行鍵)

    與nosql數(shù)據(jù)庫(kù)們一樣,row key是用來檢索記錄的主鍵。訪問HBASE table中的行,只有三種方式:

    1.通過單個(gè)row key訪問

    2.通過row key的range(正則)

    3.全表掃描

    Row key行鍵 (Row key)可以是任意字符串(最大長(zhǎng)度 是 64KB,實(shí)際應(yīng)用中長(zhǎng)度一般為 10-100bytes),在HBASE內(nèi)部,row key保存為字節(jié)數(shù)組。存儲(chǔ)時(shí),數(shù)據(jù)按照Row key的字典序(byte order)排序存儲(chǔ)。設(shè)計(jì)key時(shí),要充分排序存儲(chǔ)這個(gè)特性,將經(jīng)常一起讀取的行存儲(chǔ)放到一起。(位置相關(guān)性)

    插入到hbase中去的數(shù)據(jù),hbase會(huì)自動(dòng)排序存儲(chǔ):

    排序規(guī)則: 首先看行鍵,然后看列族名,然后看列(key)名;按字典順序

    Hbase的這個(gè)特性跟查詢效率有極大的關(guān)系

    比如:一張用來存儲(chǔ)用戶信息的表,有名字,戶籍,年齡,職業(yè)....等信息

    然后,在業(yè)務(wù)系統(tǒng)中經(jīng)常需要:

    查詢某個(gè)省的所有用戶

    經(jīng)常需要查詢某個(gè)省的指定姓的所有用戶

    思路:如果能將相同省的用戶在hbase的存儲(chǔ)文件中連續(xù)存儲(chǔ),并且能將相同省中相同姓的用戶連續(xù)存儲(chǔ),那么,上述兩個(gè)查詢需求的效率就會(huì)提高!!!

    做法:將查詢條件拼到rowkey內(nèi)

    四 HBASE客戶端API操作

    package?com.wedoctor.hbase;?import java.util.ArrayList;?import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.Cell;import org.apache.hadoop.hbase.CellUtil;import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hbase.HColumnDescriptor;import org.apache.hadoop.hbase.HTableDescriptor;import org.apache.hadoop.hbase.MasterNotRunningException;import org.apache.hadoop.hbase.TableName;import org.apache.hadoop.hbase.ZooKeeperConnectionException;import org.apache.hadoop.hbase.client.Connection;import org.apache.hadoop.hbase.client.ConnectionFactory;import org.apache.hadoop.hbase.client.Delete;import org.apache.hadoop.hbase.client.Get;import org.apache.hadoop.hbase.client.HBaseAdmin;import org.apache.hadoop.hbase.client.HConnection;import org.apache.hadoop.hbase.client.HConnectionManager;import org.apache.hadoop.hbase.client.Put;import org.apache.hadoop.hbase.client.Result;import org.apache.hadoop.hbase.client.ResultScanner;import org.apache.hadoop.hbase.client.Scan;import org.apache.hadoop.hbase.client.Table;import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;import org.apache.hadoop.hbase.filter.CompareFilter;import org.apache.hadoop.hbase.filter.FilterList;import org.apache.hadoop.hbase.filter.FilterList.Operator;import org.apache.hadoop.hbase.filter.RegexStringComparator;import org.apache.hadoop.hbase.filter.RowFilter;import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;import org.apache.hadoop.hbase.util.Bytes;import org.junit.After;import org.junit.Before;import org.junit.Test;?public class HbaseTest {? /** * 配置ss */ static Configuration config = null; private Connection connection = null; private Table table = null;? @Before public void init() throws Exception { config = HBaseConfiguration.create();// 配置 config.set("hbase.zookeeper.quorum", "master,work1,work2");// zookeeper地址 config.set("hbase.zookeeper.property.clientPort", "2181");// zookeeper端口 connection = ConnectionFactory.createConnection(config); table = connection.getTable(TableName.valueOf("user")); }? /** * 創(chuàng)建一個(gè)表 * * @throws Exception */ @Test public void createTable() throws Exception { // 創(chuàng)建表管理類 HBaseAdmin admin = new HBaseAdmin(config); // hbase表管理 // 創(chuàng)建表描述類 TableName tableName = TableName.valueOf("test3"); // 表名稱 HTableDescriptor desc = new HTableDescriptor(tableName); // 創(chuàng)建列族的描述類 HColumnDescriptor family = new HColumnDescriptor("info"); // 列族 // 將列族添加到表中 desc.addFamily(family); HColumnDescriptor family2 = new HColumnDescriptor("info2"); // 列族 // 將列族添加到表中 desc.addFamily(family2); // 創(chuàng)建表 admin.createTable(desc); // 創(chuàng)建表 }? @Test @SuppressWarnings("deprecation") public void deleteTable() throws MasterNotRunningException, ZooKeeperConnectionException, Exception { HBaseAdmin admin = new HBaseAdmin(config); admin.disableTable("test3"); admin.deleteTable("test3"); admin.close(); }? /** * 向hbase中增加數(shù)據(jù) * * @throws Exception */ @SuppressWarnings({ "deprecation", "resource" }) @Test public void insertData() throws Exception { table.setAutoFlushTo(false); table.setWriteBufferSize(534534534); ArrayList arrayList = new ArrayList(); for (int i = 21; i < 50; i++) { Put put = new Put(Bytes.toBytes("1234"+i)); put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("wangwu"+i)); put.add(Bytes.toBytes("info"), Bytes.toBytes("password"), Bytes.toBytes(1234+i)); arrayList.add(put); } //插入數(shù)據(jù) table.put(arrayList); //提交 table.flushCommits(); }? /** * 修改數(shù)據(jù) * * @throws Exception */ @Test public void uodateData() throws Exception { Put put = new Put(Bytes.toBytes("1234")); put.add(Bytes.toBytes("info"), Bytes.toBytes("namessss"), Bytes.toBytes("lisi1234")); put.add(Bytes.toBytes("info"), Bytes.toBytes("password"), Bytes.toBytes(1234)); //插入數(shù)據(jù) table.put(put); //提交 table.flushCommits(); }? /** * 刪除數(shù)據(jù) * * @throws Exception */ @Test public void deleteDate() throws Exception { Delete delete = new Delete(Bytes.toBytes("1234")); table.delete(delete); table.flushCommits(); }? /** * 單條查詢 * * @throws Exception */ @Test public void queryData() throws Exception { Get get = new Get(Bytes.toBytes("1234")); Result result = table.get(get); System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("password")))); System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("namessss")))); System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex")))); }? /** * 全表掃描 * * @throws Exception */ @Test public void scanData() throws Exception { Scan scan = new Scan(); //scan.addFamily(Bytes.toBytes("info")); //scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("password")); scan.setStartRow(Bytes.toBytes("wangsf_0")); scan.setStopRow(Bytes.toBytes("wangwu")); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("password")))); System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")))); //System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("password")))); //System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("name")))); } }? /** * 全表掃描的過濾器 * 列值過濾器 * * @throws Exception */ @Test public void scanDataByFilter1() throws Exception {? // 創(chuàng)建全表掃描的scan Scan scan = new Scan(); //過濾器:列值過濾器 SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("name"), CompareFilter.CompareOp.EQUAL, Bytes.toBytes("zhangsan2")); // 設(shè)置過濾器 scan.setFilter(filter);? // 打印結(jié)果集 ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("password"))));??????System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info"),?Bytes.toBytes("name")))); }? } /** * rowkey過濾器 * @throws Exception */ @Test public void scanDataByFilter2() throws Exception { // 創(chuàng)建全表掃描的scan Scan scan = new Scan(); //匹配rowkey以wangsenfeng開頭的 RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("^12341")); // 設(shè)置過濾器 scan.setFilter(filter); // 打印結(jié)果集 ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("password")))); System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")))); //System.out.println(Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("password")))); //System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("name")))); }? } /** * 匹配列名前綴 * @throws Exception */ @Test public void scanDataByFilter3() throws Exception { // 創(chuàng)建全表掃描的scan Scan scan = new Scan(); //匹配rowkey以wangsenfeng開頭的 ColumnPrefixFilter filter = new ColumnPrefixFilter(Bytes.toBytes("na")); // 設(shè)置過濾器 scan.setFilter(filter); // 打印結(jié)果集 ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println("rowkey:" + Bytes.toString(result.getRow())); System.out.println("info:name:" + Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")))); // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")) != null) { System.out.println("info:age:" + Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex")) != null) { System.out.println("infi:sex:" + Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("name")) != null) { System.out .println("info2:name:" + Bytes.toString(result.getValue( Bytes.toBytes("info2"), Bytes.toBytes("name")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("age")) != null) { System.out.println("info2:age:" + Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("age")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("sex")) != null) { System.out.println("info2:sex:" + Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("sex")))); } } } /** * 過濾器集合 * @throws Exception */ @Test public void scanDataByFilter4() throws Exception { // 創(chuàng)建全表掃描的scan Scan scan = new Scan(); //過濾器集合:MUST_PASS_ALL(and),MUST_PASS_ONE(or) FilterList filterList = new FilterList(Operator.MUST_PASS_ONE); //匹配rowkey以wangsenfeng開頭的 RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("^wangsenfeng")); //匹配name的值等于wangsenfeng SingleColumnValueFilter filter2 = new SingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("name"), CompareFilter.CompareOp.EQUAL, Bytes.toBytes("zhangsan")); filterList.addFilter(filter); filterList.addFilter(filter2); // 設(shè)置過濾器 scan.setFilter(filterList); // 打印結(jié)果集 ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println("rowkey:" + Bytes.toString(result.getRow())); System.out.println("info:name:" + Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")))); // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")) != null) { System.out.println("info:age:" + Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex")) != null) { System.out.println("infi:sex:" + Bytes.toInt(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("name")) != null) { System.out .println("info2:name:" + Bytes.toString(result.getValue( Bytes.toBytes("info2"), Bytes.toBytes("name")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("age")) != null) { System.out.println("info2:age:" + Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("age")))); } // 判斷取出來的值是否為空 if (result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("sex")) != null) { System.out.println("info2:sex:" + Bytes.toInt(result.getValue(Bytes.toBytes("info2"), Bytes.toBytes("sex")))); } } }? @After public void close() throws Exception { table.close(); connection.close(); }?}

    五 HBASE運(yùn)行原理

    5.1 master職責(zé)

    1.管理監(jiān)控HRegionServer,實(shí)現(xiàn)其負(fù)載均衡。

    2.處理region的分配或轉(zhuǎn)移,比如在HRegion split時(shí)分配新的HRegion;在HRegionServer退出時(shí)遷移其負(fù)責(zé)的HRegion到其他HRegionServer上。

    3.處理元數(shù)據(jù)的變更

    4.管理namespace和table的元數(shù)據(jù)(實(shí)際存儲(chǔ)在HDFS上)。

    5.權(quán)限控制(ACL)。

    6.監(jiān)控集群中所有HRegionServer的狀態(tài)(通過Heartbeat和監(jiān)聽ZooKeeper中的狀態(tài))。

    5.2 Region Server 職責(zé)

  • 管理自己所負(fù)責(zé)的region數(shù)據(jù)的讀寫。
  • 讀寫HDFS,管理Table中的數(shù)據(jù)。
  • Client直接通過HRegionServer讀寫數(shù)據(jù)(從HMaster中獲取元數(shù)據(jù),找到RowKey所在的HRegion/HRegionServer后)。
  • 刷新緩存到HDFS
  • 維護(hù)Hlog
  • 執(zhí)行壓縮
  • 負(fù)責(zé)處理Region分片
  • 5.3 zookeeper集群所起作用

  • 存放整個(gè)HBase集群的元數(shù)據(jù)以及集群的狀態(tài)信息。
  • 實(shí)現(xiàn)HMaster主從節(jié)點(diǎn)的failover。
  • 注:HMaster通過監(jiān)聽ZooKeeper中的Ephemeral節(jié)點(diǎn)(默認(rèn):/hbase/rs/*)來監(jiān)控HRegionServer的加入和宕機(jī)。

    在第一個(gè)HMaster連接到ZooKeeper時(shí)會(huì)創(chuàng)建Ephemeral節(jié)點(diǎn)(默認(rèn):/hbasae/master)來表示Active的HMaster,其后加進(jìn)來的HMaster則監(jiān)聽該Ephemeral節(jié)點(diǎn)

    如果當(dāng)前Active的HMaster宕機(jī),則該節(jié)點(diǎn)消失,因而其他HMaster得到通知,而將自身轉(zhuǎn)換成Active的HMaster,在變?yōu)锳ctive的HMaster之前,它會(huì)在/hbase/masters/下創(chuàng)建自己的Ephemeral節(jié)點(diǎn)。

    5.4 HBASE讀寫數(shù)據(jù)流程

    5.4.1 寫數(shù)據(jù)流程

    客戶端現(xiàn)在要插入一條數(shù)據(jù),rowkey=r000001, 這條數(shù)據(jù)應(yīng)該寫入到table表中的那個(gè)region中呢?

    1/ 客戶端要連接zookeeper, 從zk的/hbase節(jié)點(diǎn)找到hbase:meta表所在的regionserver(host:port);

    2/ regionserver掃描hbase:meta中的每個(gè)region的起始行健,對(duì)比r000001這條數(shù)據(jù)在那個(gè)region的范圍內(nèi);

    3/ 從對(duì)應(yīng)的 info:server key中存儲(chǔ)了region是有哪個(gè)regionserver(host:port)在負(fù)責(zé)的;

    4/ 客戶端直接請(qǐng)求對(duì)應(yīng)的regionserver;

    5/ regionserver接收到客戶端發(fā)來的請(qǐng)求之后,就會(huì)將數(shù)據(jù)寫入到region中

    5.4.2 讀數(shù)據(jù)流程

    客戶端現(xiàn)在要查詢r(jià)owkey=r000001這條數(shù)據(jù),那么這個(gè)流程是什么樣子的呢?

    1/ 首先Client連接zookeeper, 找到hbase:meta表所在的regionserver;

    2/ 請(qǐng)求對(duì)應(yīng)的regionserver,掃描hbase:meta表,根據(jù)namespace、表名和rowkey在meta表中找到r00001所在的region是由那個(gè)regionserver負(fù)責(zé)的;

    3/找到這個(gè)region對(duì)應(yīng)的regionserver

    4/ regionserver收到了請(qǐng)求之后,掃描對(duì)應(yīng)的region返回?cái)?shù)據(jù)到Client

    (先從MemStore找數(shù)據(jù),如果沒有,再到BlockCache里面讀;BlockCache還沒有,再到StoreFile上讀(為了讀取的效率);

    如果是從StoreFile里面讀取的數(shù)據(jù),不是直接返回給客戶端,而是先寫入BlockCache,再返回給客戶端。)

    注:客戶會(huì)緩存這些位置信息,然而第二步它只是緩存當(dāng)前RowKey對(duì)應(yīng)的HRegion的位置,因而如果下一個(gè)要查的RowKey不在同一個(gè)HRegion中,則需要繼續(xù)查詢hbase:meta所在的HRegion,然而隨著時(shí)間的推移,客戶端緩存的位置信息越來越多,以至于不需要再次查找hbase:meta Table的信息,除非某個(gè)HRegion因?yàn)殄礄C(jī)或Split被移動(dòng),此時(shí)需要重新查詢并且更新緩存。

    5.4.3 數(shù)據(jù)flush過程

    1)當(dāng)MemStore數(shù)據(jù)達(dá)到閾值(默認(rèn)是128M,老版本是64M),將數(shù)據(jù)刷到硬盤,將內(nèi)存中的數(shù)據(jù)刪除,同時(shí)刪除HLog中的歷史數(shù)據(jù);

    2)并將數(shù)據(jù)存儲(chǔ)到HDFS中;

    3)在HLog中做標(biāo)記點(diǎn)。

    5.4.4 數(shù)據(jù)合并過程

    1)當(dāng)數(shù)據(jù)塊達(dá)到3塊,Hmaster觸發(fā)合并操作,Region將數(shù)據(jù)塊加載到本地,進(jìn)行合并;

    2)當(dāng)合并的數(shù)據(jù)超過256M,進(jìn)行拆分,將拆分后的Region分配給不同的HregionServer管理;

    3)當(dāng)HregionServer宕機(jī)后,將HregionServer上的hlog拆分,然后分配給不同的HregionServer加載,修改.META.;

    4)注意:HLog會(huì)同步到HDFS。

    5.5 hbase:meta表

    hbase:meta表存儲(chǔ)了所有用戶HRegion的位置信息:

    Rowkey:tableName,regionStartKey,regionId,replicaId等;

    info列族:這個(gè)列族包含三個(gè)列,他們分別是:

    info:regioninfo列:

    regionId,tableName,startKey,endKey,offline,split,replicaId;

    info:server列:HRegionServer對(duì)應(yīng)的server:port;

    info:serverstartcode列:HRegionServer的啟動(dòng)時(shí)間戳。

    5.6 Region Server內(nèi)部機(jī)制

    • WAL即Write Ahead Log,在早期版本中稱為HLog,它是HDFS上的一個(gè)文件,如其名字所表示的,所有寫操作都會(huì)先保證將數(shù)據(jù)寫入這個(gè)Log文件后,才會(huì)真正更新MemStore,最后寫入HFile中。WAL文件存儲(chǔ)在/hbase/WALs/${HRegionServer_Name}的目錄中
    • BlockCache是一個(gè)讀緩存,即“引用局部性”原理(也應(yīng)用于CPU,分空間局部性和時(shí)間局部性,空間局部性是指CPU在某一時(shí)刻需要某個(gè)數(shù)據(jù),那么有很大的概率在一下時(shí)刻它需要的數(shù)據(jù)在其附近;時(shí)間局部性是指某個(gè)數(shù)據(jù)在被訪問過一次后,它有很大的概率在不久的將來會(huì)被再次的訪問),將數(shù)據(jù)預(yù)讀取到內(nèi)存中,以提升讀的性能。
    • HRegion是一個(gè)Table中的一個(gè)Region在一個(gè)HRegionServer中的表達(dá)。一個(gè)Table可以有一個(gè)或多個(gè)Region,他們可以在一個(gè)相同的HRegionServer上,也可以分布在不同的HRegionServer上,一個(gè)HRegionServer可以有多個(gè)HRegion,他們分別屬于不同的Table。HRegion由多個(gè)Store(HStore)構(gòu)成,每個(gè)HStore對(duì)應(yīng)了一個(gè)Table在這個(gè)HRegion中的一個(gè)Column Family,即每個(gè)Column Family就是一個(gè)集中的存儲(chǔ)單元,因而最好將具有相近IO特性的Column存儲(chǔ)在一個(gè)Column Family,以實(shí)現(xiàn)高效讀取(數(shù)據(jù)局部性原理,可以提高緩存的命中率)。HStore是HBase中存儲(chǔ)的核心,它實(shí)現(xiàn)了讀寫HDFS功能,一個(gè)HStore由一個(gè)MemStore 和0個(gè)或多個(gè)StoreFile組成。
    • MemStore是一個(gè)寫緩存(In Memory Sorted Buffer),所有數(shù)據(jù)的寫在完成WAL日志寫后,會(huì) 寫入MemStore中,由MemStore根據(jù)一定的算法將數(shù)據(jù)Flush到地層HDFS文件中(HFile),通常每個(gè)HRegion中的每個(gè) Column Family有一個(gè)自己的MemStore。
    • HFile(StoreFile) 用于存儲(chǔ)HBase的數(shù)據(jù)(Cell/KeyValue)。在HFile中的數(shù)據(jù)是按RowKey、Column Family、Column排序,對(duì)相同的Cell(即這三個(gè)值都一樣),則按timestamp倒序排列。
    • FLUSH詳述
  • 每一次Put/Delete請(qǐng)求都是先寫入到MemStore中,當(dāng)MemStore滿后會(huì)Flush成一個(gè)新的StoreFile(底層實(shí)現(xiàn)是HFile),即一個(gè)HStore(Column Family)可以有0個(gè)或多個(gè)StoreFile(HFile)。
  • 當(dāng)一個(gè)HRegion中的所有MemStore的大小總和超過了hbase.hregion.memstore.flush.size的大小,默認(rèn)128MB。此時(shí)當(dāng)前的HRegion中所有的MemStore會(huì)Flush到HDFS中。
  • 當(dāng)全局MemStore的大小超過了hbase.regionserver.global.memstore.upperLimit的大小,默認(rèn)40%的內(nèi)存使用量。此時(shí)當(dāng)前HRegionServer中所有HRegion中的MemStore都會(huì)Flush到HDFS中,Flush順序是MemStore大小的倒序(一個(gè)HRegion中所有MemStore總和作為該HRegion的MemStore的大小還是選取最大的MemStore作為參考?有待考證),直到總體的MemStore使用量低于hbase.regionserver.global.memstore.lowerLimit,默認(rèn)38%的內(nèi)存使用量。
  • 當(dāng)前HRegionServer中WAL的大小超過了hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs的數(shù)量,當(dāng)前HRegionServer中所有HRegion中的MemStore都會(huì)Flush到HDFS中,Flush使用時(shí)間順序,最早的MemStore先Flush直到WAL的數(shù)量少于hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs這里說這兩個(gè)相乘的默認(rèn)大小是2GB,查代碼,hbase.regionserver.max.logs默認(rèn)值是32,而hbase.regionserver.hlog.blocksize默認(rèn)是32MB。但不管怎么樣,因?yàn)檫@個(gè)大小超過限制引起的Flush不是一件好事,可能引起長(zhǎng)時(shí)間的延遲
  • 六.HBASE優(yōu)化

    6.1 高可用

    在HBase中Hmaster負(fù)責(zé)監(jiān)控RegionServer的生命周期,均衡RegionServer的負(fù)載,如果Hmaster掛掉了,那么整個(gè)HBase集群將陷入不健康的狀態(tài),并且此時(shí)的工作狀態(tài)并不會(huì)維持太久。所以HBase支持對(duì)Hmaster的高可用配置。

    1.關(guān)閉HBase集群(如果沒有開啟則跳過此步)

    bin/stop-hbase.sh

    2.在conf目錄下創(chuàng)建backup-masters文件

    touch conf/backup-masters

    3.在backup-masters文件中配置高可用HMaster節(jié)點(diǎn)

    echo?hadoop110?>?conf/backup-masters

    4.將整個(gè)conf目錄scp到其他節(jié)點(diǎn)

    scp?-r?conf/?hadoop110:/opt/module/hbase/

    6.2 預(yù)分區(qū)

    每一個(gè)region維護(hù)著startRow與endRowKey,如果加入的數(shù)據(jù)符合某個(gè)region維護(hù)的rowKey范圍,則該數(shù)據(jù)交給這個(gè)region維護(hù)。那么依照這個(gè)原則,我們可以將數(shù)據(jù)所要投放的分區(qū)提前大致的規(guī)劃好,以提高HBase性能。

    1.手動(dòng)設(shè)定預(yù)分區(qū)

    hbase> create 'staff1','info','partition1',SPLITS => ['1000','2000','3000','4000']

    2.生成16進(jìn)制序列預(yù)分區(qū)

    create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

    3.按照文件中設(shè)置的規(guī)則預(yù)分區(qū)

    創(chuàng)建splits.txt文件內(nèi)容如下:

    aaaa

    bbbb

    cccc

    dddd

    然后執(zhí)行:

    create 'staff3','partition3',SPLITS_FILE => 'splits.txt'

    6.3 RowKey設(shè)計(jì)

    一條數(shù)據(jù)的唯一標(biāo)識(shí)就是rowkey,那么這條數(shù)據(jù)存儲(chǔ)于哪個(gè)分區(qū),取決于rowkey處于哪個(gè)一個(gè)預(yù)分區(qū)的區(qū)間內(nèi),設(shè)計(jì)rowkey的主要目的 ,就是讓數(shù)據(jù)均勻的分布于所有的region中,在一定程度上防止數(shù)據(jù)傾斜。接下來我們就談一談rowkey常用的設(shè)計(jì)方案。

    1.生成隨機(jī)數(shù)、hash、散列值

    比如:

    原本rowKey為1001的,SHA1后變成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7

    原本rowKey為3001的,SHA1后變成:49042c54de64a1e9bf0b33e00245660ef92dc7bd

    原本rowKey為5001的,SHA1后變成:7b61dec07e02c188790670af43e717f0f46e8913

    在做此操作之前,一般我們會(huì)選擇從數(shù)據(jù)集中抽取樣本,來決定什么樣的rowKey來Hash后作為每個(gè)分區(qū)的臨界值。

    2.字符串反轉(zhuǎn)

    20170524000001轉(zhuǎn)成10000042507102

    20170524000002轉(zhuǎn)成20000042507102

    3.字符串拼接

    20170524000001_a12e

    20170524000001_93i7

    6.4 內(nèi)存優(yōu)化

    HBase操作過程中需要大量的內(nèi)存開銷,畢竟Table是可以緩存在內(nèi)存中的,一般會(huì)分配整個(gè)可用內(nèi)存的70%給HBase的Java堆。但是不建議分配非常大的堆內(nèi)存,因?yàn)镚C過程持續(xù)太久會(huì)導(dǎo)致RegionServer處于長(zhǎng)期不可用狀態(tài),一般16~48G內(nèi)存就可以了,如果因?yàn)榭蚣苷加脙?nèi)存過高導(dǎo)致系統(tǒng)內(nèi)存不足,框架一樣會(huì)被系統(tǒng)服務(wù)拖死。

    6.5 基礎(chǔ)優(yōu)化

    1.允許在HDFS的文件中追加內(nèi)容

    hdfs-site.xml、hbase-site.xml

    屬性:dfs.support.append

    解釋:開啟HDFS追加同步,可以優(yōu)秀的配合HBase的數(shù)據(jù)同步和持久化。默認(rèn)值為true。

    2.優(yōu)化DataNode允許的最大文件打開數(shù)

    hdfs-site.xml

    屬性:dfs.datanode.max.transfer.threads

    解釋:HBase一般都會(huì)同一時(shí)間操作大量的文件,根據(jù)集群的數(shù)量和規(guī)模以及數(shù)據(jù)動(dòng)作,設(shè)置為4096或者更高。默認(rèn)值:4096

    3.優(yōu)化延遲高的數(shù)據(jù)操作的等待時(shí)間

    hdfs-site.xml

    屬性:dfs.image.transfer.timeout

    解釋:如果對(duì)于某一次數(shù)據(jù)操作來講,延遲非常高,socket需要等待更長(zhǎng)的時(shí)間,建議把該值設(shè)置為更大的值(默認(rèn)60000毫秒),以確保socket不會(huì)被timeout掉。

    4.優(yōu)化數(shù)據(jù)的寫入效率

    mapred-site.xml

    屬性:

    mapreduce.map.output.compress

    mapreduce.map.output.compress.codec

    解釋:開啟這兩個(gè)數(shù)據(jù)可以大大提高文件的寫入效率,減少寫入時(shí)間。第一個(gè)屬性值修改為true,第二個(gè)屬性值修改為:org.apache.hadoop.io.compress.GzipCodec或者其他壓縮方式。

    5.設(shè)置RPC監(jiān)聽數(shù)量

    hbase-site.xml

    屬性:hbase.regionserver.handler.count

    解釋:默認(rèn)值為30,用于指定RPC監(jiān)聽的數(shù)量,可以根據(jù)客戶端的請(qǐng)求數(shù)進(jìn)行調(diào)整,讀寫請(qǐng)求較多時(shí),增加此值。

    6.優(yōu)化HStore文件大小

    hbase-site.xml

    屬性:hbase.hregion.max.filesize

    解釋:默認(rèn)值10737418240(10GB),如果需要運(yùn)行HBase的MR任務(wù),可以減小此值,因?yàn)橐粋€(gè)region對(duì)應(yīng)一個(gè)map任務(wù),如果單個(gè)region過大,會(huì)導(dǎo)致map任務(wù)執(zhí)行時(shí)間過長(zhǎng)。該值的意思就是,如果HFile的大小達(dá)到這個(gè)數(shù)值,則這個(gè)region會(huì)被切分為兩個(gè)Hfile。

    7.優(yōu)化hbase客戶端緩存

    hbase-site.xml

    屬性:hbase.client.write.buffer

    解釋:用于指定HBase客戶端緩存,增大該值可以減少RPC調(diào)用次數(shù),但是會(huì)消耗更多內(nèi)存,反之則反之。一般我們需要設(shè)定一定的緩存大小,以達(dá)到減少RPC次數(shù)的目的。

    8.指定scan.next掃描HBase所獲取的行數(shù)

    hbase-site.xml

    屬性:hbase.client.scanner.caching

    解釋:用于指定scan.next方法獲取的默認(rèn)行數(shù),值越大,消耗內(nèi)存越大。

    9.flush、compact、split機(jī)制

    當(dāng)MemStore達(dá)到閾值,將Memstore中的數(shù)據(jù)Flush進(jìn)Storefile;compact機(jī)制則是把flush出來的小文件合并成大的Storefile文件。split則是當(dāng)Region達(dá)到閾值,會(huì)把過大的Region一分為二。

    涉及屬性:

    即:128M就是Memstore的默認(rèn)閾值

    hbase.hregion.memstore.flush.size:134217728hbase.regionserver.global.memstore.upperLimit:0.4hbase.regionserver.global.memstore.lowerLimit:0.38

    即:

    當(dāng)MemStore使用內(nèi)存總量達(dá)到hbase.regionserver.global.memstore.upperLimit指定值時(shí),將會(huì)有多個(gè)MemStores flush到文件中,MemStore flush 順序是按照大小降序執(zhí)行的,直到刷新到MemStore使用內(nèi)存略小于lowerLimit即:這個(gè)參數(shù)的作用是當(dāng)單個(gè)HRegion內(nèi)所有的Memstore大小總和超過指定值時(shí),flush該HRegion的所有memstore。RegionServer的flush是通過將請(qǐng)求添加一個(gè)隊(duì)列,模擬生產(chǎn)消費(fèi)模型來異步處理的。那這里就有一個(gè)問題,當(dāng)隊(duì)列來不及消費(fèi),產(chǎn)生大量積壓請(qǐng)求時(shí),可能會(huì)導(dǎo)致內(nèi)存陡增,最壞的情況是觸發(fā)OOM。

    總結(jié)

    以上是生活随笔為你收集整理的/opt/hbase/conf 中不能启动hbase_Hbase从入门到入坑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。