大數據系列——Hbase學習筆記

1. Hbase簡介

  • Hadoop-Database根據'bigtable'論文實現的
  • 分佈式 可擴展的大數據存儲技術
  • 隨機訪問 實時讀寫海量數據
  • 存儲數 '十億行 百萬列'的數據
  • 高可靠性、高性能、面向列、可伸縮分佈式存儲系統
  • hbase的底層存儲基於hdfs
  • 利用Zookeeper做爲協調工具

2. Hbase是什麼?

  • 分佈式開源數據庫,基於hadoop分佈式文件系統(HDFS)
  • 模仿提供了Google文件系統的BigTable數據庫全部功能
  • 處理很是龐大的表java

    • 數十億行 百萬列
    • 利用mapreduce計算數據,利用zookeeper協調資源
  • HBase是一款NoSQL

3. 行存儲和列存儲

  • 行存儲:mysql oracle底層基於行存儲數據的mysql

    • 查詢數據須要全表掃描,效率較低
    • 對數據壓縮支持不太好
  • 列存儲:hbase底層基於列存儲數據的sql

    • 查詢數據不需作全表掃描
    • 支持較好的數據壓縮

4. Hbase的特色

  • 能夠分佈式存儲海量的數據
  • 具備容錯能力強,數據高可靠的特色
  • HBase是一個列式NoSQL數據庫
  • 數據存儲的結構是按照列進行存儲

5. Hbase的安裝部署

==安裝hbase高可用集羣以前首先要保證zookeeper和hadoop已經安裝完成==shell

  • 準備安裝包

     hbase-1.1.5-bin.tar.gz數據庫

  • 集羣的規劃apache

    • uplooking01: master
    • uplooking02: master
    • uplooking03: regionserver
    • uplooking04: regionserver
    • uplooking05: regionserver
  • 解壓安裝包vim

    [root@uplooking01: /soft]:
            tar -zxvf hbase-1.1.5-bin.tar.gz  -C /opt/
  • 重命名數組

    [root@uplooking01: /opt]:
            mv hbase-1.1.5/ hbase
  • 配置環境變量緩存

    [root@uplooking01: /opt]:
        #配置HBASE的環境變量
        export HBASE_HOME=/opt/hbase
        export PATH=$PATH:$HBASE_HOME/bin
  • 配置vim hbase-env.sh安全

    [root@uplooking01: /opt/hbase/conf]:
        vim  hbase-env.sh
    export JAVA_HOME=/opt/jdk
    export HBASE_MANAGES_ZK=false   #不使用hbase自帶的zookeeper
    export HBASE_CLASSPATH=/opt/hadoop/etc/hadoop
  • 配置hbase-site.xml

    [root@uplooking01: /opt/hbase/conf]:
        vim  hbase-site.xml
    <configuration>
        <property>
        <name>hbase.rootdir</name>
        <value>hdfs://ns1/hbase</value>
        </property>
    
        <property>
        <name>hbase.tmp.dir</name>
        <value>/opt/hbase/tmp</value>
        </property>
    
        <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
        </property>
    
        <property>
        <name>hbase.zookeeper.quorum</name>
        <value>uplooking03:2181,uplooking04:2181,uplooking05:2181</value>
        </property>
    </configuration>
  • 配置 regionservers

    [root@uplooking01: /opt/hbase/conf]:
        vim  regionservers
    uplooking03
    uplooking04
    uplooking05
  • 分發文件

    [root@uplooking01: /opt]:
        scp -r hbase uplooking02:/opt
        scp -r hbase uplooking03:/opt
        scp -r hbase uplooking04:/opt
        scp -r hbase uplooking05:/opt
        
        scp /etc/profile uplooking02:/etc/
        scp /etc/profile uplooking03:/etc/
        scp /etc/profile uplooking04:/etc/
        scp /etc/profile uplooking05:/etc/
    source /etc/profile(全部節點都作,要使環境變量生效)
  • 啓動hbase集羣

    start-hbase.sh
  • 單獨啓動master

    [root@uplooking02:/]
        hbase-daemon.sh start master
  • 注意事項

    ==啓動hbase集羣必定要保證整個集羣的時間一致==

  • ==附加(通常不會有這種狀況)==

    若是啓動集羣執行start-hbase.sh,master節點能夠啓動,可是regionserver節點不能啓動,可是單獨啓動regionserver(hbase-daemon.sh start regionserver)是能夠啓動的,也沒有問題,name就須要拷貝一個jar包,

     將HADOOP_HOME/share/hadoop/common/lib下的htrace-core-3.0.4.jar  複製到$HBASE_HOME/lib下

6. Hbase的體系結構(模型)

6.1 邏輯結構(模型)

  • 表(table)

    • 劃分數據集合的概念,和傳統的db中的表的概念是同樣的
  • 行鍵(rowKey)

    • 對應關係數據庫中的主鍵,做用就是惟一標示一行記錄
    • 獲取hbase中的一個記錄(數據),要經過行鍵來獲取
    • 行鍵是字節數組, 任何字符串均可以做爲行鍵
    • 表中的行根據行鍵(row key)進行排序 ,數據按照Row key的字節序(byte order)排序存儲
  • 列簇(列族)columnFamily

    • 簡單的認爲是一系列「列」的集合
  • 列限定符(column Qualifier)

    • 或者叫
    • 每一個列簇均可以有多個列
  • 時間戳(version)

    • 在單元格中能夠存放多個版本的數據
  • 單元格(cell)

    • 主要用來存儲數據
    • 單元格的定位要經過三級定位才能定位到具體的單元格
  • 三級定位

    • 行鍵+(列族:列)+時間戳

6.2 物理結構(模型)

  • Zookeeper

    • 分佈式協調
  • Master

    • HMaster沒有單點問題,HBase中能夠啓動多個HMaster
    • 負責Table和Region的管理工做
    • 管理用戶對Table的增、刪、改、查操做
    • RegionServer的負載均衡
    • 調整Region分佈 ,在Region Split後,負責新Region的分配
    • 在HRegionServer停機後,負責失效HRegionServer上的Regions遷移
  • RegionServer

    • RegionServer主要負責響應用戶I/O請求
    • 向HDFS文件系統中讀寫數據,是HBase中最核心的模塊
    • HLog部分和多個Region部分
  • Hlog

    • HLog保存着用戶操做hbase的日誌
    • ==實現了Write Ahead Log (WAL)預寫日誌==
    • Hlog會刪除已存儲到StoreFile中的數據
  • Region

    • 區域
    • 保存了row-key的固定區域範圍的數據
    • 一個Hregion對應一個Region
    • 一個Hregion對應多個Hstore
  • Hstore

    • 對應一個列簇(列族)
    • 一個Hstore包含一個MemStore(內存儲) 和多個StoreFile
  • MemStore

    • 內存儲
    • 內存中的一塊區域,一個Hstore對應一個MemStore
    • 當MemStore中的內容存放不下了就會刷出到硬盤以一個個的StoreFile存儲
  • StoreFile

    • 其實就是數據的存儲位置
    • 對HFile的封裝**
  • Hfile

    • Hadoop File
    • Hdfs的一個文件對象

7. Hbase讀寫數據的流程

  • zookeeper(尋找元數據信息)

    • get /hbase/meta-region-server
  • 找到提供元數據信息訪問的regionserver
  • 找"hbase:meta"表,再去查找要請求哪一個regionser來讀寫數據

8. Hbase的Shell操做

  • 列出全部的命名空間(至關於mysql中的show databases)

    • list_namespace
  • 列出指定命名空間下的全部表

    • list_namespace_tables 'ns1'
  • 建立命名空間

    • create_namespace 'ns1'
  • 建立表

    • create 'ns1:t1','f1'
  • 禁用表,由於刪除表以前首先須要禁用了

    • disable 'ns1:t1'
  • 啓用表

    • enable 'ns1:t1'
  • 刪除表

    • drop 'ns1:t1'
  • 添加數據

    • put 'ns1:t1','row001','f1:name','xiaohua'
  • 查詢數據

    • get 'ns1:t1','row001',{COLUMN=>'f1:name'}
  • 刪除數據

    • delete 'ns1:t1','row001','f1:name'
  • 刪除一行數據

    • deleteall 'ns1:t1','row001'
  • 統計表的行數

    • count 'ns1:t1'

9. Hbase中的版本數據

  • 建立Hbase表時指定列族的顯示版本數

    • create 'ns1:t1',{NAME=>'f1',VERSIONS=>3}
  • 修改Hbase表中的列族的顯示版本數

    • alter 'ns1:t1',{NAME=>'f1',VERSIONS=>5}
  • 查詢指定版本數的數據

    • get 'ns1:t1',{COLUMN=>'f1:name',VERSIONS=>3}
  • ==版本號的做用==

    根據顯示的版本數,查詢出來想要版本的時間戳,根據時間戳找出具體值

10. Hbase中API的基本操做

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hbase-version>1.1.5</hbase-version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-client</artifactId>
        <version>${hbase-version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-server</artifactId>
        <version>${hbase-version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-hbase-handler</artifactId>
        <version>2.1.0</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>
public class HbaseTest {
    //添加數據
    @Test
    public void testPut() throws IOException {
        Configuration conf = HBaseConfiguration.create();
        //指定zk的地址
        conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
        Connection conn = ConnectionFactory.createConnection(conf);
        Table table = conn.getTable(TableName.valueOf("ns1:t1"));
        Put put = new Put(Bytes.toBytes("row001"));
        put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("admin02"));
        table.put(put);
    }


    //刪除數據
    @Test
    public void testDelete() throws IOException {
        Configuration conf = HBaseConfiguration.create();
        //指定zk的地址
        conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
        Connection conn = ConnectionFactory.createConnection(conf);
        Table table = conn.getTable(TableName.valueOf("ns1:t1"));
        Delete delete = new Delete(Bytes.toBytes("row001"));
        table.delete(delete);
    }

    //查詢數據
    @Test
    public void testGet() throws IOException {
        Configuration conf = HBaseConfiguration.create();
        //指定zk的地址
        conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
        Connection conn = ConnectionFactory.createConnection(conf);
        Table table = conn.getTable(TableName.valueOf("ns1:t1"));
        Get get = new Get(Bytes.toBytes("row001"));
        Result result = table.get(get);
        String s = Bytes.toString(result.getValue(Bytes.toBytes("f1"),Bytes.toBytes("name")));
        System.out.println(s);
    }
}

11. Hbase中的API的管理操做

public class HbaseAdminTest {

    private Connection connection;

    @Before
    public void init() throws Exception {
        Configuration conf = new Configuration();
        conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
        connection = ConnectionFactory.createConnection(conf);
    }

    /**
     * 建立表
     *
     * @throws Exception
     */
    @Test
    public void testCreateTable() throws Exception {
        //獲取管理對象
        Admin admin = connection.getAdmin();
        HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("t2"));
        HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes("f1"));
        htd.addFamily(hcd);
        admin.createTable(htd);
    }


    /**
     * 列出全部的表
     * @throws Exception
     */
    @Test
    public void testListTableNames() throws Exception {
        //獲取管理對象
        Admin admin = connection.getAdmin();
        TableName[] tableNames = admin.listTableNames("ns1:.*");
        for (TableName tableName : tableNames) {
            System.out.println(tableName);
        }
    }

}

12. Hbase高級查詢

//查詢數據
@Test
public void testScan() throws IOException {
    Configuration conf = HBaseConfiguration.create();
    //指定zk的地址
    conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
    Connection conn = ConnectionFactory.createConnection(conf);
    Table table = conn.getTable(TableName.valueOf("ns1:t1"));
    Scan scan = new Scan();
    byte[] cf = Bytes.toBytes("f1");
    byte[] column = Bytes.toBytes("name");
    Filter filter = new SingleColumnValueFilter(cf, column, CompareFilter.CompareOp.EQUAL, Bytes.toBytes("admin123"));
    scan.setFilter(filter);
    //獲取包含多行數據的對象
    ResultScanner resultScanner = table.getScanner(scan);
    for (Result result : resultScanner) {
        System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("f1"), Bytes.toBytes("age"))));
    }
}

13. 百萬數據的插入

13.1 mysql百萬數據寫入

​ 耗時約20分鐘
本身測試10分鐘

8800000ms,插入15851742tiao數據

13.2 hbase百萬數據的寫入

/**
 * 百萬數據的插入
 */
public class HbaseMiTest {

    private Connection connection;

    @Before
    public void init() throws Exception {
        Configuration conf = new Configuration();
        conf.set("hbase.zookeeper.quorum", "uplooking03:2181,uplooking04:2181,uplooking05:2181");
        connection = ConnectionFactory.createConnection(conf);
    }

    @Test
    public void test01() throws IOException {
        HTable table = (HTable) connection.getTable(TableName.valueOf("ns1:t1"));
        //不使用每一個put操做都刷出一次
        table.setAutoFlush(false);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            Put put = new Put(Bytes.toBytes("row" + i));
            //關閉預寫日誌,可是不建議使用,由於這樣作不安全
            put.setWriteToWAL(false);
            put.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("name"), Bytes.toBytes("admin" + i));
            table.put(put);
            if (i % 100000 == 0) {
                table.flushCommits();
            }
        }
        table.flushCommits();
        long endTime = System.currentTimeMillis();
        System.out.println("總耗時:" + (endTime - startTime) + "ms");
    }
}

大約耗時27s
本身測試,1分20秒 590/80=7.4倍
查詢一行是9秒
97602ms,插入15851742tiao數據 8800/175=50倍

14. Hbase中的手動切分region

split 'ns1:t1','row040'

15. Hbase手動移動region

move 'f6e6164514db53d660c5414df1f3864e','uplooking05,1602

**0,1539222350164'**

16. Hbase中row-key的設計

  • 行健的熱點問題

​ 是因爲行健類似、連續且數據量過大操做成單region的數據量過大,進而影響讀寫效率

​ 行健應該儘可能的隨機、不要出現連續行健。

​ 常見的行健設計就是,好比手機號碼倒置+時間戳,好比隨機前綴+關係型數據庫中的主鍵

​ 由於hbase提供的查詢內容很是很是low,可是全部關於hbase的查詢只能經過rowkey,因此

​ 在設計行健的時候,應該考慮將盡可能多的查詢條件放到rowkey中去,造成的行健就成爲複合鍵

列族的設計:

​ cf1----->"columnFamily"

​ cf2----->"cf"

​ 建議hbase表是高表,不建議寬表,由於寬表擁有的列族不少,操做並跨越的文件(HFile)就不少,效率會有相應影響,

​ 反之建議使用高表,列族不宜過多(列族通常使用一個)。

​ 在設計表的時候,各個列/列族名稱不宜過長,由於hbase須要對這些數據在內存中作緩存,作索引,進而影響內存容量,因此建議不易過長,以便可以在內存中容納更多的數據。至於閱讀性,有項目文檔搞定。

17. Hbase中客戶端工具

HbaseExplorer

相關文章
相關標籤/搜索