<noframes id="1rvnr"><progress id="1rvnr"><meter id="1rvnr"></meter></progress>

      <big id="1rvnr"><progress id="1rvnr"><font id="1rvnr"></font></progress></big>

      <sub id="1rvnr"><thead id="1rvnr"><cite id="1rvnr"></cite></thead></sub>
        <progress id="1rvnr"></progress>

          <big id="1rvnr"></big>
            <sub id="1rvnr"></sub>

            Hbase專欄 - 大數據專欄 - noSQL數據庫專欄 - 中國存儲網首頁
            1. 入門
            1.1. 介紹
            1.2. 快速開始
            2. Apache HBase (TM)配置
            2.1. 基礎條件
            2.2. HBase 運行模式: 獨立和分布式
            2.3. 配置文件
            2.4. 配置示例
            2.5. 重要配置
             
            3. 升級
            3.1. 從 0.94.x 升級到 0.96.x
            3.2. 從 0.92.x 升級到 0.94.x
            3.3. 從 0.90.x 升級到 0.92.x
            3.4. 從0.20x或0.89x升級到0.90.x
             
            4. HBase Shell
            4.1. 使用腳本
            4.2. Shell 技巧
            5. 數據模型
            5.1. 概念視圖
            5.2. 物理視圖
            5.3.
            5.4.
            5.5. 列族
            5.6. Cells
            5.7. Data Model Operations
            5.8. 版本
            5.9. 排序
            5.10. 列元數據
            5.11. Joins
            5.12. ACID
            6. HBase 和 Schema 設計
            6.1. Schema 創建
            6.2. column families的數量
            6.3. Rowkey 設計
            6.4. 版本數量
            6.5. 支持的數據類型
            6.6. Joins
            6.7. 生存時間 (TTL)
            6.8. 保留刪除的單元
            6.9. 第二索引和替代查詢路徑
            6.10. 限制
            6.11. 模式設計用例
            6.12. 操作和性能配置選項
             
            7. HBase 和 MapReduce
            7.1. Map-Task 分割
            7.2. HBase MapReduce 示例
            7.3. 在MapReduce工作中訪問其他 HBase 表
            7.4. 推測執行
            8. HBase安全
            8.1. 安全客戶端訪問 HBase
            8.2. 訪問控制
            8.3. 安全批量加載
            9. 架構
            9.1. 概述
            9.2. 目錄表
            9.3. 客戶端
            9.4. 客戶請求過濾器
            9.5. Master
            9.6. RegionServer
            9.7. 分區(Regions)
            9.8. 批量加載
            9.9. HDFS
            10. 外部 APIs
            10.1. 非Java語言和 JVM交互
            10.2. REST
            10.3. Thrift
            10.4. C/C++ Apache HBase Client
            11. 性能調優
            11.1. 操作系統
            11.2. 網絡
            11.3. Java
            11.4. HBase 配置
            11.5. ZooKeeper
            11.6. Schema 設計
            11.7. HBase General Patterns
            11.8. 寫到 HBase
            11.9. 從 HBase讀取
            11.10. 從 HBase刪除
            11.11. HDFS
            11.12. Amazon EC2
            11.13. 案例
            12. 故障排除和調試 HBase
            12.1. 通用指引
            12.2. Logs
            12.3. 資源
            12.4. 工具
            12.5. 客戶端
            12.6. MapReduce
            12.7. NameNode
            12.8. 網絡
            12.9. RegionServer
            12.10. Master
            12.11. ZooKeeper
            12.12. Amazon EC2
            12.13. HBase 和 Hadoop 版本相關
            12.14. 案例
            13. 案例研究
            13.1. 概要
            13.2. Schema 設計
            13.3. 性能/故障排除
            14. HBase 運維管理
            14.1. HBase 工具和實用程序
            14.2. 分區管理
            14.3. 節點管理
            14.4. HBase 度量(Metrics)
            14.5. HBase 監控
            14.6. Cluster 復制
            14.7. HBase 備份
            14.8. 容量規劃
            15. 創建和開發 HBase
            15.1. HBase 倉庫
            15.2. IDEs
            15.3. 創建 HBase
            15.4. 添加 Apache HBase 發行版到Apache的 Maven Repository
            15.5. 生成HBase 參考指南
            15.6. 更新 hbase.apache.org
            15.7. 測試
            15.8. Maven 創建命令
            15.9. 加入
            15.10. 開發
            15.11. 提交補丁
            16. ZooKeeper
            16.1. 和已有的ZooKeeper一起使用
            16.2. 通過ZooKeeper 的SASL 認證
            17. 社區
            17.1. 決策
            17.2. 社區角色
            A. FAQ
            B. 深入hbck
            B.1. 運行 hbck 以查找不一致
            B.2. 不一致(Inconsistencies)
            B.3. 局部修補
            B.4. 分區重疊修補
            C. HBase中的壓縮
            C.1. CompressionTest 工具
            C.2. hbase.regionserver.codecs
            C.3. LZO
            C.4. GZIP
            C.5. SNAPPY
            C.6. 修改壓縮 Schemes
            D. YCSB: Yahoo! 云服務評估和 HBase
             
            E. HFile 格式版本 2
            E.1. Motivation
            E.2. HFile 格式版本 1 概覽
            E.3. HBase 文件格式帶 inline blocks (version 2)
            F. HBase的其他信息
            F.1. HBase 視頻
            F.2. HBase 展示 (Slides)
            F.3. HBase 論文
            F.4. HBase 網站
            F.5. HBase 書籍
            F.6. Hadoop 書籍
            G. HBase 歷史
             
            H. HBase 和 Apache 軟件基金會(ASF)
            H.1. ASF開發進程
            H.2. ASF 報告板
            I. Enabling Dapper-like Tracing in HBase
            I.1. SpanReceivers
            I.2. Client Modifications
            J. 0.95 RPC Specification
            J.1. Goals
            J.2. TODO
            J.3. RPC
            J.4. Notes
            詞匯表

            表索引

            2.1. Hadoop版本兼容性比較表
            5.1. Table webtable
            5.2. ColumnFamily anchor
            5.3. ColumnFamily contents
            8.1. Operation To Permission Mapping

            Apache HBase參考指南

            HBase HBase 官方文檔中文版

            Revision History
            Revision 0.97.0-SNAPSHOT2013-04-07T14:59
            中文版翻譯整理 周海漢


            譯者:HBase新版 0.97 文檔和0.90版相比,變化較大,文檔補充更新了很多內容,章節調整較大。本翻譯文檔的部分工作基于顏開工作。英文原文地址在此處。舊版0.90版由顏開翻譯文檔在此處。0.97版翻譯最后更新請到此處( http://www.wingo-ir.com/manuals/hbase-v097/index.html )瀏覽。反饋和參與請到此處 (https://github.com/ablozhou/hbasedoc_cn/)或訪問我的blog(http://abloz.com),或給我發email。

            可以通過瀏覽器直接存儲為pdf或本地文件。

            貢獻者:

            周海漢郵箱:ablozhou@gmail.com, QQ:7268188 網址:http://abloz.com/
            顏開郵箱: yankaycom@gmail.com, 網址:http://www.yankay.com/


            摘要

            這是 Apache HBase (TM)的官方文檔。 HBase是一個分布式,版本化,面向列的數據庫,構建在 Apache HadoopApache ZooKeeper之上。

             


            目錄

             

            這本書是 HBase 的官方指南。 版本為 0.95-SNAPSHOT 。可以在HBase官網上找到它。也可以在 javadoc, JIRAwiki 找到更多的資料。

            此書正在編輯中。 可以向 HBase 官方提供補丁JIRA.

            這個版本系譯者水平限制,沒有理解清楚或不需要翻譯的地方保留英文原文。

            最前面的話

            若這是你第一次踏入分布式計算的精彩世界,你會感到這是一個有趣的年代。分布式計算是很難的,做一個分布式系統需要很多軟硬件和網絡的技能。你的集群可以會因為各式各樣的錯誤發生故障。比如HBase本身的Bug,錯誤的配置(包括操作系統),硬件的故障(網卡和磁盤甚至內存) 如果你一直在寫單機程序的話,你需要重新開始學習。這里就是一個好的起點: 分布式計算的謬論.

            Chapter 1. 入門

            1.1. 介紹

            Section 1.2, “快速開始”會介紹如何運行一個單機版的HBase.他運行在本地磁盤上。 Section 2, “配置” 會介紹如何運行一個分布式的HBase。他運行在HDFS上

            1.2. 快速開始

            本指南介紹了在單機安裝HBase的方法。會引導你通過shell創建一個表,插入一行,然后刪除它,最后停止HBase。只要10分鐘就可以完成以下的操作。

            1.2.1. 下載解壓最新版本

            選擇一個 Apache 下載鏡像,下載 HBase Releases. 點擊 stable目錄,然后下載后綴為 .tar.gz 的文件; 例如 hbase-0.95-SNAPSHOT.tar.gz.

            解壓縮,然后進入到那個要解壓的目錄.

            $ tar xfz hbase-0.95-SNAPSHOT.tar.gz
            $ cd hbase-0.95-SNAPSHOT
            

            現在你已經可以啟動HBase了。但是你可能需要先編輯 conf/hbase-site.xml 去配置hbase.rootdir,來選擇HBase將數據寫到哪個目錄 .

            <?xml version="1.0"?>
            <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
            <configuration>
              <property>
                <name>hbase.rootdir</name>
                <value>file:///DIRECTORY/hbase</value>
              </property>
            </configuration>
            
            

            DIRECTORY 替換成你期望寫文件的目錄. 默認 hbase.rootdir 是指向 /tmp/hbase-${user.name} ,也就說你會在重啟后丟失數據(重啟的時候操作系統會清理/tmp目錄)

            1.2.2. 啟動 HBase

            現在啟動HBase:

            $ ./bin/start-hbase.sh
            starting Master, logging to logs/hbase-user-master-example.org.out

            現在你運行的是單機模式的Hbaes。所有的服務都運行在一個JVM上,包括HBase和Zookeeper。HBase的日志放在logs目錄,當你啟動出問題的時候,可以檢查這個日志。

            是否安裝了 java ?

            你需要確認安裝了Oracle的1.6 版本的java.如果你在命令行鍵入java有反應說明你安裝了Java。如果沒有裝,你需要先安裝,然后編輯conf/hbase-env.sh,將其中的JAVA_HOME指向到你Java的安裝目錄。

            1.2.3. Shell 練習

            shell連接你的HBase

            $ ./bin/hbase shell
            HBase Shell; enter 'help<RETURN>' for list of supported commands.
            Type "exit<RETURN>" to leave the HBase Shell
            Version: 0.90.0, r1001068, Fri Sep 24 13:55:42 PDT 2010
            
            hbase(main):001:0> 

            輸入 help 然后 <RETURN> 可以看到一列shell命令。這里的幫助很詳細,要注意的是表名,行和列需要加引號。

            創建一個名為 test 的表,這個表只有一個 列族 為 cf。可以列出所有的表來檢查創建情況,然后插入些值。

            hbase(main):003:0> create 'test', 'cf'
            0 row(s) in 1.2200 seconds
            hbase(main):003:0> list 'table'
            test
            1 row(s) in 0.0550 seconds
            hbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1'
            0 row(s) in 0.0560 seconds
            hbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2'
            0 row(s) in 0.0370 seconds
            hbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3'
            0 row(s) in 0.0450 seconds

            以上我們分別插入了3行。第一個行key為row1, 列為 cf:a, 值是 value1。HBase中的列是由 列族前綴和列的名字組成的,以冒號間隔。例如這一行的列名就是a.

            檢查插入情況.

            Scan這個表,操作如下

            hbase(main):007:0> scan 'test'
            ROW        COLUMN+CELL
            row1       column=cf:a, timestamp=1288380727188, value=value1
            row2       column=cf:b, timestamp=1288380738440, value=value2
            row3       column=cf:c, timestamp=1288380747365, value=value3
            3 row(s) in 0.0590 seconds

            Get一行,操作如下

            hbase(main):008:0> get 'test', 'row1'
            COLUMN      CELL
            cf:a        timestamp=1288380727188, value=value1
            1 row(s) in 0.0400 seconds

            disable 再 drop 這張表,可以清除你剛剛的操作

            hbase(main):012:0> disable 'test'
            0 row(s) in 1.0930 seconds
            hbase(main):013:0> drop 'test'
            0 row(s) in 0.0770 seconds 

            關閉shell

            hbase(main):014:0> exit

            1.2.4. 停止 HBase

            運行停止腳本來停止HBase.

            $ ./bin/stop-hbase.sh
            stopping hbase...............

            1.2.5. 下一步該做什么

            以上步驟僅僅適用于實驗和測試。接下來你可以看 Section 2., “配置” ,我們會介紹不同的HBase運行模式,運行分布式HBase中需要的軟件 和如何配置。

            2. 配置

             

            本章是慢速開始配置指導。

            HBase有如下需要,請仔細閱讀本章節以確保所有的需要都被滿足。如果需求沒有能滿足,就有可能遇到莫名其妙的錯誤甚至丟失數據。

            HBase使用和Hadoop一樣配置系統。要配置部署,編輯conf/hbase-env.sh文件中的環境變量——該配置文件主要啟動腳本用于獲取已啟動的集群——然后增加配置到XML文件,如同覆蓋HBase缺省配置,告訴HBase用什么文件系統, 全部ZooKeeper位置 [1] 。

            在分布模式下運行時,在編輯HBase配置文件之后,確認將conf目錄復制到集群中的每個節點。HBase不會自動同步。使用rsync.

            [1] 小心編輯XML。確認關閉所有元素。采用 xmllint 或類似工具確認文檔編輯后是良好格式化的。

            2.1. 基礎條件

            This section lists required services and some required system configuration.

            2.1.1 java

            和Hadoop一樣,HBase需要Oracle版本的Java6.除了那個有問題的u18版本其他的都可以用,最好用最新的。

            2.1. 操作系統

            2.1.2.1. ssh

            必須安裝sshsshd 也必須運行,這樣Hadoop的腳本才可以遠程操控其他的Hadoop和HBase進程。ssh之間必須都打通,不用密碼都可以登錄,詳細方法可以Google一下 ("ssh passwordless login").

            2.1.2.2. DNS

            HBase使用本地 hostname 才獲得IP地址. 正反向的DNS都是可以的.

            如果你的機器有多個接口,HBase會使用hostname指向的主接口.

            如果還不夠,你可以設置 hbase.regionserver.dns.interface 來指定主接口。當然你的整個集群的配置文件都必須一致,每個主機都使用相同的網絡接口

            還有一種方法是設置 hbase.regionserver.dns.nameserver來指定nameserver,不使用系統帶的.

            2.1.2.3. Loopback IP

            HBase expects the loopback IP address to be 127.0.0.1. Ubuntu and some other distributions, for example, will default to 127.0.1.1 and this will cause problems for you.

            /etc/hosts should look something like this:

                        127.0.0.1 localhost
                        127.0.0.1 ubuntu.ubuntu-domain ubuntu
            

            2.1.2.4. NTP

            集群的時鐘要保證基本的一致。稍有不一致是可以容忍的,但是很大的不一致會造成奇怪的行為。 運行 NTP 或者其他什么東西來同步你的時間.

            如果你查詢的時候或者是遇到奇怪的故障,可以檢查一下系統時間是否正確!

            2.1.2.5.  ulimitnproc

            HBase是數據庫,會在同一時間使用很多的文件句柄。大多數linux系統使用的默認值1024是不能滿足的,會導致FAQ: Why do I see "java.io.IOException...(Too many open files)" in my logs?異常。還可能會發生這樣的異常

                  2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Exception increateBlockOutputStream java.io.EOFException
                  2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient: Abandoning block blk_-6935524980745310745_1391901
                  

            所以你需要修改你的最大文件句柄限制。可以設置到10k。大致的數學運算如下:每列族至少有1個存儲文件(StoreFile) 可能達到5-6個如果區域有壓力。將每列族的存儲文件平均數目和每區域服務器的平均區域數目相乘。例如:假設一個模式有3個列族,每個列族有3個存儲文件,每個區域服務器有100個區域,JVM 將打開3 * 3 * 100 = 900 個文件描述符(不包含打開的jar文件,配置文件等)

            你還需要修改 hbase 用戶的 nproc,在壓力下,如果過低會造成 OutOfMemoryError異常[3] [4]。

            需要澄清的,這兩個設置是針對操作系統的,不是HBase本身的。有一個常見的錯誤是HBase運行的用戶,和設置最大值的用戶不是一個用戶。在HBase啟動的時候,第一行日志會現在ulimit信息,確保其正確。[5]

            2.1.2.5.1. 在Ubuntu上設置ulimit

            如果你使用的是Ubuntu,你可以這樣設置:

            在文件 /etc/security/limits.conf 添加一行,如:

            hadoop  -       nofile  32768

            可以把 hadoop 替換成你運行HBase和Hadoop的用戶。如果你用兩個用戶,你就需要配兩個。還有配nproc hard 和 soft limits. 如:

            hadoop soft/hard nproc 32000

            .

            /etc/pam.d/common-session 加上這一行:

            session required  pam_limits.so

            否則在 /etc/security/limits.conf上的配置不會生效.

            還有注銷再登錄,這些配置才能生效!

            2.1.2.6. Windows

            HBase沒有怎么在Windows下測試過。所以不推薦在Windows下運行.

            如果你實在是想運行,需要安裝Cygwin 并虛擬一個unix環境.詳情請看 Windows 安裝指導 . 或者 搜索郵件列表找找最近的關于windows的注意點

            2.1.3. hadoop

            選擇 Hadoop 版本對HBase部署很關鍵。下表顯示不同HBase支持的Hadoop版本信息。基于HBase版本,應該選擇合適的Hadoop版本。我們沒有綁定 Hadoop 發行版選擇。可以從Apache使用 Hadoop 發行版,或了解一下Hadoop發行商產品: http://wiki.apache.org/hadoop/Distributions%20and%20Commercial%20Support

            Table 2.1. Hadoop版本兼容性比較表

            HBase-0.92.x HBase-0.94.x HBase-0.96
            Hadoop-0.20.205 S X X
            Hadoop-0.22.x S X X
            Hadoop-1.0.x S S S
            Hadoop-1.1.x NT S S
            Hadoop-0.23.x X S NT
            Hadoop-2.x X S S


            S = supported and tested,支持
            X = not supported,不支持
            NT = not tested enough.可以運行但測試不充分

            由于 HBase 依賴 Hadoop,它配套發布了一個Hadoop jar 文件在它的 lib 下。該套裝jar僅用于獨立模式。在分布式模式下,Hadoop版本必須和HBase下的版本一致。用你運行的分布式Hadoop版本jar文件替換HBase lib目錄下的Hadoop jar文件,以避免版本不匹配問題。確認替換了集群中所有HBase下的jar文件。Hadoop版本不匹配問題有不同表現,但看起來都像掛掉了。

            2.1.3.1. Apache HBase 0.92 and 0.94

            HBase 0.92 and 0.94 versions can work with Hadoop versions, 0.20.205, 0.22.x, 1.0.x, and 1.1.x. HBase-0.94 can additionally work with Hadoop-0.23.x and 2.x, but you may have to recompile the code using the specific maven profile (see top level pom.xml)

            2.1.3.2. Apache HBase 0.96

            Apache HBase 0.96.0 requires Apache Hadoop 1.x at a minimum, and it can run equally well on hadoop-2.0. As of Apache HBase 0.96.x, Apache Hadoop 1.0.x at least is required. We will no longer run properly on older Hadoops such as 0.20.205 or branch-0.20-append. Do not move to Apache HBase 0.96.x if you cannot upgrade your Hadoop[6].

            2.1.3.3. Hadoop versions 0.20.x - 1.x

            HBase will lose data unless it is running on an HDFS that has a durable sync implementation. DO NOT use Hadoop 0.20.2, Hadoop 0.20.203.0, and Hadoop 0.20.204.0 which DO NOT have this attribute. Currently only Hadoop versions 0.20.205.x or any release in excess of this version -- this includes hadoop-1.0.0 -- have a working, durable sync[7]. Sync has to be explicitly enabled by setting dfs.support.append equal to true on both the client side -- in hbase-site.xml -- and on the serverside in hdfs-site.xml (The sync facility HBase needs is a subset of the append code path).

              <property>      <name>dfs.support.append</name>      <value>true</value>    </property>          

            You will have to restart your cluster after making this edit. Ignore the chicken-little comment you'll find in the hdfs-default.xml in the description for thedfs.support.append configuration.

            2.1.3.4. Hadoop 安全性

            HBase運行在Hadoop 0.20.x上,就可以使用其中的安全特性 -- 只要你用這兩個版本0.20S 和CDH3B3,然后把hadoop.jar替換掉就可以了.

            2.1.3.5. dfs.datanode.max.xcievers

            一個 Hadoop HDFS Datanode 有一個同時處理文件的上限. 這個參數叫 xcievers (Hadoop的作者把這個單詞拼錯了). 在你加載之前,先確認下你有沒有配置這個文件conf/hdfs-site.xml里面的xceivers參數,至少要有4096:

                  <property>
                    <name>dfs.datanode.max.xcievers</name>
                    <value>4096</value>
                  </property>
                  

            對于HDFS修改配置要記得重啟.

            如果沒有這一項配置,你可能會遇到奇怪的失敗。你會在Datanode的日志中看到xcievers exceeded,但是運行起來會報 missing blocks錯誤。例如: 10/12/08 20:10:31 INFO hdfs.DFSClient: Could not obtain block blk_XXXXXXXXXXXXXXXXXXXXXX_YYYYYYYY from any node: java.io.IOException: No live nodes contain current block. Will get new block locations from namenode and retry... [5]

            See also Section 13.3.4, “Case Study #4 (xcievers Config)”

            2.2. HBase運行模式:單機和分布式

            HBase有兩個運行模式: Section 2.4.1, “單機模式”Section 2.4.2, “分布式模式”. 默認是單機模式,如果要分布式模式你需要編輯 conf 文件夾中的配置文件.

            不管是什么模式,你都需要編輯 conf/hbase-env.sh來告知HBase java的安裝路徑.在這個文件里你還可以設置HBase的運行環境,諸如 heapsize和其他 JVM有關的選項, 還有Log文件地址,等等. 設置 JAVA_HOME指向 java安裝的路徑.

            2.21. 單機模式

            這是默認的模式,在 Section 1.2, “快速開始” 一章中介紹的就是這個模式. 在單機模式中,HBase使用本地文件系統,而不是HDFS ,所有的服務和zooKeeper都運作在一個JVM中。zookeep監聽一個端口,這樣客戶端就可以連接HBase了。

            2.2.2. 分布式模式

            分布式模式分兩種。偽分布式模式是把進程運行在一臺機器上,但不是一個JVM.而完全分布式模式就是把整個服務被分布在各個節點上了 [6].

            分布式模式需要使用 Hadoop Distributed File System (HDFS).可以參見 HDFS需求和指導來獲得關于安裝HDFS的指導。在操作HBase之前,你要確認HDFS可以正常運作。

            在我們安裝之后,你需要確認你的偽分布式模式或者 完全分布式模式的配置是否正確。這兩個模式可以使用同一個驗證腳本Section 2.2.3, “運行和確認你的安裝”

            2.2.2.1. 偽分布式模式

            偽分布式模式是一個相對簡單的分布式模式。這個模式是用來測試的。不能把這個模式用于生產環節,也不能用于測試性能。

            你確認HDFS安裝成功之后,就可以先編輯 conf/hbase-site.xml。在這個文件你可以加入自己的配置,這個配置會覆蓋 Section 2.6.1.1, “HBase 默認配置” and Section 2.2.2.2.3, “HDFS客戶端配置”. 運行HBase需要設置hbase.rootdir 屬性.該屬性是指HBase在HDFS中使用的目錄的位置。例如,要想 /hbase 目錄,讓namenode 監聽locahost的9000端口,只有一份數據拷貝(HDFS默認是3份拷貝)。可以在 hbase-site.xml 寫上如下內容

            <configuration>
              ...
              <property>
                <name>hbase.rootdir</name>
                <value>hdfs://localhost:9000/hbase</value>
                <description>The directory shared by RegionServers.
                </description>
              </property>
              <property>
                <name>dfs.replication</name>
                <value>1</value>
                <description>The replication count for HLog & HFile storage. Should not be greater than HDFS datanode count.
                </description>
              </property>
              ...
            </configuration>
            

            Note

            讓HBase自己創建 hbase.rootdir

            Note

            上面我們綁定到 localhost. 也就是說除了本機,其他機器連不上HBase。所以你需要設置成別的,才能使用它。

            現在可以跳到 Section 2.2.3, “運行和確認你的安裝” 來運行和確認你的偽分布式模式安裝了。 [7]

            2.2.2.1.1. 偽分布模式配置文件

            下面是偽分布模式設置的配置文件示例。

            hdfs-site.xml
            <configuration>    ...    <property>      <name>dfs.name.dir</name>      <value>/Users/local/user.name/hdfs-data-name</value>    </property>    <property>      <name>dfs.data.dir</name>      <value>/Users/local/user.name/hdfs-data</value>    </property>    <property>      <name>dfs.replication</name>      <value>1</value>    </property>    ...  </configuration>  
            hbase-site.xml
            <configuration>    ...    <property>      <name>hbase.rootdir</name>      <value>hdfs://localhost:8020/hbase</value>    </property>    <property>      <name>hbase.zookeeper.quorum</name>      <value>localhost</value>    </property>    <property>      <name>hbase.cluster.distributed</name>      <value>true</value>    </property>    ...  </configuration>  
            2.2.2.1.2. 偽分布模式附加
            2.2.2.1.2.1. 啟動

            啟動初始 HBase 集群...

            % bin/start-hbase.sh

            在同一服務器啟動額外備份主服務器

            % bin/local-master-backup.sh start 1

            ... '1' 表示使用端口 60001 & 60011, 該備份主服務器及其log文件放在logs/hbase-${USER}-1-master-${HOSTNAME}.log.

            啟動多個備份主服務器...

            % bin/local-master-backup.sh start 2 3

            可以啟動到 9 個備份服務器 (總數10 個).

            啟動更多 regionservers...

            % bin/local-regionservers.sh start 1

            '1' 表示使用端口 60201 & 60301 ,log文件在 logs/hbase-${USER}-1-regionserver-${HOSTNAME}.log.

            在剛運行的regionserver上增加 4 個額外 regionservers ...

            % bin/local-regionservers.sh start 2 3 4 5

            支持到 99 個額外regionservers (總100個).

            2.2.2.1.2.2. 停止

            假設想停止備份主服務器 # 1, 運行...

            % cat /tmp/hbase-${USER}-1-master.pid |xargs kill -9

            注意 bin/local-master-backup.sh 停止 1 會嘗試停止主服務器相關集群。

            停止單獨 regionserver, 運行...

            % bin/local-regionservers.sh stop 1  	                

            2.2.2.2. 完全分布式模式

            要想運行完全分布式模式,你要進行如下配置,先在 hbase-site.xml, 加一個屬性 hbase.cluster.distributed 設置為 true 然后把 hbase.rootdir 設置為HDFS的NameNode的位置。 例如,你的namenode運行在namenode.example.org,端口是9000 你期望的目錄是 /hbase,使用如下的配置

            <configuration>
              ...
              <property>
                <name>hbase.rootdir</name>
                <value>hdfs://namenode.example.org:9000/hbase</value>
                <description>The directory shared by RegionServers.
                </description>
              </property>
              <property>
                <name>hbase.cluster.distributed</name>
                <value>true</value>
                <description>The mode the cluster will be in. Possible values are
                  false: standalone and pseudo-distributed setups with managed Zookeeper
                  true: fully-distributed with unmanaged Zookeeper Quorum (see hbase-env.sh)
                </description>
              </property>
              ...
            </configuration>
            
            2.2.2.2.1. regionservers

            完全分布式模式的還需要修改conf/regionservers. 在 Section 2.7.1.2, “regionservers 列出了你希望運行的全部 HRegionServer,一行寫一個host (就像Hadoop里面的 slaves 一樣). 列在這里的server會隨著集群的啟動而啟動,集群的停止而停止.

            2.2.2.2.2. ZooKeeper 和 HBase

             

            2.2.2.2.3. HDFS客戶端配置

            如果你希望Hadoop集群上做HDFS 客戶端配置 ,例如你的HDFS客戶端的配置和服務端的不一樣。按照如下的方法配置,HBase就能看到你的配置信息:

            • hbase-env.sh里將HBASE_CLASSPATH環境變量加上HADOOP_CONF_DIR

            • ${HBASE_HOME}/conf下面加一個 hdfs-site.xml (或者 hadoop-site.xml) ,最好是軟連接

            • 如果你的HDFS客戶端的配置不多的話,你可以把這些加到 hbase-site.xml上面.

            例如HDFS的配置 dfs.replication.你希望復制5份,而不是默認的3份。如果你不照上面的做的話,HBase只會復制3份。

            2.2.3. 運行和確認你的安裝

            首先確認你的HDFS是運行著的。你可以運行HADOOP_HOME中的 bin/start-hdfs.sh 來啟動HDFS.你可以通過put命令來測試放一個文件,然后有get命令來讀這個文件。通常情況下HBase是不會運行mapreduce的。所以比不需要檢查這些。

            如果你自己管理ZooKeeper集群,你需要確認它是運行著的。如果是HBase托管,ZoopKeeper會隨HBase啟動。

            用如下命令啟動HBase:

            bin/start-hbase.sh
            這個腳本在HBASE_HOME目錄里面。

            你現在已經啟動HBase了。HBase把log記在 logs 子目錄里面. 當HBase啟動出問題的時候,可以看看Log.

            HBase也有一個界面,上面會列出重要的屬性。默認是在Master的60010端口上H (HBase RegionServers 會默認綁定 60020端口,在端口60030上有一個展示信息的界面 ).如果Master運行在 master.example.org,端口是默認的話,你可以用瀏覽器在 http://master.example.org:60010看到主界面. .

            一旦HBase啟動,參見Section 1.2.3, “Shell 練習”可以看到如何建表,插入數據,scan你的表,還有disable這個表,最后把它刪掉。

            可以在HBase Shell停止HBase

            $ ./bin/stop-hbase.sh
            stopping hbase...............

            停止操作需要一些時間,你的集群越大,停的時間可能會越長。如果你正在運行一個分布式的操作,要確認在HBase徹底停止之前,Hadoop不能停.



             

            2.3. 配置文件

             

            HBase的配置系統和Hadoop一樣。在conf/hbase-env.sh配置系統的部署信息和環境變量。 -- 這個配置會被啟動shell使用 -- 然后在XML文件里配置信息,覆蓋默認的配置。告知HBase使用什么目錄地址,ZooKeeper的位置等等信息。 [10] .

            當你使用分布式模式的時間,當你編輯完一個文件之后,記得要把這個文件復制到整個集群的conf 目錄下。HBase不會幫你做這些,你得用 rsync.

            2.3.1. hbase-site.xmlhbase-default.xml

            正如Hadoop放置HDFS的配置文件hdfs-site.xml,HBase的配置文件是 conf/hbase-site.xml. 你可以在 Section 2.3.1.1, “HBase 默認配置”找到配置的屬性列表。你也可以看有代碼里面的hbase-default.xml文件,他在src/main/resources目錄下。

            不是所有的配置都在 hbase-default.xml出現.只要改了代碼,配置就有可能改變,所以唯一了解這些被改過的配置的辦法是讀源代碼本身。

            要注意的是,要重啟集群才能是配置生效。

            2.3.1.1. HBase 默認配置

            HBase 默認配置

            該文檔是用hbase默認配置文件生成的,文件源是 hbase-default.xml

            hbase.rootdir

            這個目錄是region server的共享目錄,用來持久化HBase。URL需要是'完全正確'的,還要包含文件系統的scheme。例如,要表示hdfs中的'/hbase'目錄,namenode 運行在namenode.example.org的9090端口。則需要設置為hdfs://namenode.example.org:9000/hbase。默認情況下HBase是寫到/tmp的。不改這個配置,數據會在重啟的時候丟失。

            默認: file:///tmp/hbase-${user.name}/hbase

            hbase.master.port

            HBase的Master的端口.

            默認: 60000

            hbase.cluster.distributed

            HBase的運行模式。false是單機模式,true是分布式模式。若為false,HBase和Zookeeper會運行在同一個JVM里面。

            默認: false

            hbase.tmp.dir

            本地文件系統的臨時文件夾。可以修改到一個更為持久的目錄上。(/tmp會在重啟時清楚)

            默認:${java.io.tmpdir}/hbase-${user.name}

            hbase.local.dir

            作為本地存儲,位于本地文件系統的路徑。

            默認: ${hbase.tmp.dir}/local/

            hbase.master.info.port

            HBase Master web 界面端口. 設置為-1 意味著你不想讓他運行。

            默認: 60010

            hbase.master.info.bindAddress

            HBase Master web 界面綁定的端口

            默認: 0.0.0.0

            hbase.client.write.buffer

            HTable客戶端的寫緩沖的默認大小。這個值越大,需要消耗的內存越大。因為緩沖在客戶端和服務端都有實例,所以需要消耗客戶端和服務端兩個地方的內存。得到的好處是,可以減少RPC的次數。可以這樣估算服務器端被占用的內存: hbase.client.write.buffer * hbase.regionserver.handler.count

            默認: 2097152

            hbase.regionserver.port

            HBase RegionServer綁定的端口

            默認: 60020

            hbase.regionserver.info.port

            HBase RegionServer web 界面綁定的端口 設置為 -1 意味這你不想與運行 RegionServer 界面.

            默認: 60030

            hbase.regionserver.info.port.auto

            Master或RegionServer是否要動態搜一個可以用的端口來綁定界面。當hbase.regionserver.info.port已經被占用的時候,可以搜一個空閑的端口綁定。這個功能在測試的時候很有用。默認關閉。

            默認: false

            hbase.regionserver.info.bindAddress

            HBase RegionServer web 界面的IP地址

            默認: 0.0.0.0

            hbase.regionserver.class

            RegionServer 使用的接口。客戶端打開代理來連接region server的時候會使用到。

            默認: org.apache.hadoop.hbase.ipc.HRegionInterface

            hbase.client.pause

            通常的客戶端暫停時間。最多的用法是客戶端在重試前的等待時間。比如失敗的get操作和region查詢操作等都很可能用到。

            默認: 1000

            hbase.client.retries.number

            最大重試次數。所有需重試操作的最大值。例如從root region服務器獲取root region,Get單元值,行Update操作等等。這是最大重試錯誤的值。  Default: 10.

            默認: 10

            hbase.bulkload.retries.number

            最大重試次數。 原子批加載嘗試的迭代最大次數。 0 永不放棄。默認: 0.

            默認: 0

             

            hbase.client.scanner.caching

            當調用Scanner的next方法,而值又不在緩存里的時候,從服務端一次獲取的行數。越大的值意味著Scanner會快一些,但是會占用更多的內存。當緩沖被占滿的時候,next方法調用會越來越慢。慢到一定程度,可能會導致超時。例如超過了hbase.regionserver.lease.period。

            默認: 100

            hbase.client.keyvalue.maxsize

            一個KeyValue實例的最大size.這個是用來設置存儲文件中的單個entry的大小上界。因為一個KeyValue是不能分割的,所以可以避免因為數據過大導致region不可分割。明智的做法是把它設為可以被最大region size整除的數。如果設置為0或者更小,就會禁用這個檢查。默認10MB。

            默認: 10485760

            hbase.regionserver.lease.period

            客戶端租用HRegion server 期限,即超時閥值。單位是毫秒。默認情況下,客戶端必須在這個時間內發一條信息,否則視為死掉。

            默認: 60000

            hbase.regionserver.handler.count

            RegionServers受理的RPC Server實例數量。對于Master來說,這個屬性是Master受理的handler數量

            默認: 10

            hbase.regionserver.msginterval

            RegionServer 發消息給 Master 時間間隔,單位是毫秒

            默認: 3000

            hbase.regionserver.optionallogflushinterval

            將Hlog同步到HDFS的間隔。如果Hlog沒有積累到一定的數量,到了時間,也會觸發同步。默認是1秒,單位毫秒。

            默認: 1000

            hbase.regionserver.regionSplitLimit

            region的數量到了這個值后就不會在分裂了。這不是一個region數量的硬性限制。但是起到了一定指導性的作用,到了這個值就該停止分裂了。默認是MAX_INT.就是說不阻止分裂。

            默認: 2147483647

            hbase.regionserver.logroll.period

            提交commit log的間隔,不管有沒有寫足夠的值。

            默認: 3600000

            hbase.regionserver.hlog.reader.impl

            HLog file reader 的實現.

            默認: org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogReader

            hbase.regionserver.hlog.writer.impl

            HLog file writer 的實現.

            默認: org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogWriter

             
             
            hbase.regionserver.nbreservationblocks

            儲備的內存block的數量(譯者注:就像石油儲備一樣)。當發生out of memory 異常的時候,我們可以用這些內存在RegionServer停止之前做清理操作。

            默認: 4

            hbase.zookeeper.dns.interface

            當使用DNS的時候,Zookeeper用來上報的IP地址的網絡接口名字。

            默認: default

            hbase.zookeeper.dns.nameserver

            當使用DNS的時候,Zookeepr使用的DNS的域名或者IP 地址,Zookeeper用它來確定和master用來進行通訊的域名.

            默認: default

            hbase.regionserver.dns.interface

            當使用DNS的時候,RegionServer用來上報的IP地址的網絡接口名字。

            默認: default

            hbase.regionserver.dns.nameserver

            當使用DNS的時候,RegionServer使用的DNS的域名或者IP 地址,RegionServer用它來確定和master用來進行通訊的域名.

            默認: default

            hbase.master.dns.interface

            當使用DNS的時候,Master用來上報的IP地址的網絡接口名字。

            默認: default

            hbase.master.dns.nameserver

            當使用DNS的時候,RegionServer使用的DNS的域名或者IP 地址,Master用它來確定用來進行通訊的域名.

            默認: default

            hbase.balancer.period

            Master執行region balancer的間隔。

            默認: 300000

            hbase.regions.slop

            當任一區域服務器有average + (average * slop)個分區,將會執行重新均衡。默認 20% slop .

            默認:0.2

            hbase.master.logcleaner.ttl

            Hlog存在于.oldlogdir 文件夾的最長時間, 超過了就會被 Master 的線程清理掉.

            默認: 600000

            hbase.master.logcleaner.plugins

            LogsCleaner服務會執行的一組LogCleanerDelegat。值用逗號間隔的文本表示。這些WAL/HLog cleaners會按順序調用。可以把先調用的放在前面。你可以實現自己的LogCleanerDelegat,加到Classpath下,然后在這里寫下類的全稱。一般都是加在默認值的前面。

            默認: org.apache.hadoop.hbase.master.TimeToLiveLogCleaner

            hbase.regionserver.global.memstore.upperLimit

            單個region server的全部memtores的最大值。超過這個值,一個新的update操作會被掛起,強制執行flush操作。

            默認: 0.4

            hbase.regionserver.global.memstore.lowerLimit

            當強制執行flush操作的時候,當低于這個值的時候,flush會停止。默認是堆大小的 35% . 如果這個值和 hbase.regionserver.global.memstore.upperLimit 相同就意味著當update操作因為內存限制被掛起時,會盡量少的執行flush(譯者注:一旦執行flush,值就會比下限要低,不再執行)

            默認: 0.35

            hbase.server.thread.wakefrequency

            service工作的sleep間隔,單位毫秒。 可以作為service線程的sleep間隔,比如log roller.

            默認: 10000

            hbase.server.versionfile.writeattempts

            退出前嘗試寫版本文件的次數。每次嘗試由 hbase.server.thread.wakefrequency 毫秒數間隔。

            默認: 3

             
            hbase.hregion.memstore.flush.size

            當memstore的大小超過這個值的時候,會flush到磁盤。這個值被一個線程每隔hbase.server.thread.wakefrequency檢查一下。

            默認:134217728

            hbase.hregion.preclose.flush.size

            當一個region中的memstore的大小大于這個值的時候,我們又觸發了close.會先運行“pre-flush”操作,清理這個需要關閉的memstore,然后將這個region下線。當一個region下線了,我們無法再進行任何寫操作。如果一個memstore很大的時候,flush操作會消耗很多時間。"pre-flush"操作意味著在region下線之前,會先把memstore清空。這樣在最終執行close操作的時候,flush操作會很快。

            默認: 5242880

            hbase.hregion.memstore.block.multiplier

            如果memstore有hbase.hregion.memstore.block.multiplier倍數的hbase.hregion.flush.size的大小,就會阻塞update操作。這是為了預防在update高峰期會導致的失控。如果不設上界,flush的時候會花很長的時間來合并或者分割,最壞的情況就是引發out of memory異常。(譯者注:內存操作的速度和磁盤不匹配,需要等一等。原文似乎有誤)

            默認: 2

            hbase.hregion.memstore.mslab.enabled

            體驗特性:啟用memStore分配本地緩沖區。這個特性是為了防止在大量寫負載的時候堆的碎片過多。這可以減少GC操作的頻率。(GC有可能會Stop the world)(譯者注:實現的原理相當于預分配內存,而不是每一個值都要從堆里分配)

            默認: true

            hbase.hregion.max.filesize

            最大HStoreFile大小。若某個列族的HStoreFile增長達到這個值,這個Hegion會被切割成兩個。 默認: 10G.

            默認:10737418240

            hbase.hstore.compactionThreshold

            當一個HStore含有多于這個值的HStoreFiles(每一個memstore flush產生一個HStoreFile)的時候,會執行一個合并操作,把這HStoreFiles寫成一個。這個值越大,需要合并的時間就越長。

            默認: 3

            hbase.hstore.blockingStoreFiles

            當一個HStore含有多于這個值的HStoreFiles(每一個memstore flush產生一個HStoreFile)的時候,會執行一個合并操作,update會阻塞直到合并完成,直到超過了hbase.hstore.blockingWaitTime的值

            默認: 7

            hbase.hstore.blockingWaitTime

            hbase.hstore.blockingStoreFiles所限制的StoreFile數量會導致update阻塞,這個時間是來限制阻塞時間的。當超過了這個時間,HRegion會停止阻塞update操作,不過合并還有沒有完成。默認為90s.

            默認: 90000

            hbase.hstore.compaction.max

            每個“小”合并的HStoreFiles最大數量。

            默認: 10

            hbase.hregion.majorcompaction

            一個Region中的所有HStoreFile的major compactions的時間間隔。默認是1天。 設置為0就是禁用這個功能。

            默認: 86400000

            hbase.storescanner.parallel.seek.enable

            允許 StoreFileScanner 并行搜索 StoreScanner, 一個在特定條件下降低延遲的特性。

            默認: false

             
            hbase.storescanner.parallel.seek.threads

            并行搜索特性打開后,默認線程池大小。

            默認: 10

             

            hbase.mapreduce.hfileoutputformat.blocksize

            MapReduce中HFileOutputFormat可以寫 storefiles/hfiles. 這個值是hfile的blocksize的最小值。通常在HBase寫Hfile的時候,bloocksize是由table schema(HColumnDescriptor)決定的,但是在mapreduce寫的時候,我們無法獲取schema中blocksize。這個值越小,你的索引就越大,你隨機訪問需要獲取的數據就越小。如果你的cell都很小,而且你需要更快的隨機訪問,可以把這個值調低。

            默認: 65536

            hfile.block.cache.size

            分配給HFile/StoreFile的block cache占最大堆(-Xmx setting)的比例。默認0.25意思是分配25%,設置為0就是禁用,但不推薦。

            默認:0.25

            hbase.hash.type

            哈希函數使用的哈希算法。可以選擇兩個值:: murmur (MurmurHash) 和 jenkins (JenkinsHash). 這個哈希是給 bloom filters用的.

            默認: murmur

            hfile.block.index.cacheonwrite

            This allows to put non-root multi-level index blocks into the block cache at the time the index is being written.

            Default: false

            hfile.index.block.max.size

            When the size of a leaf-level, intermediate-level, or root-level index block in a multi-level block index grows to this size, the block is written out and a new block is started.

            Default: 131072

            hfile.format.version

            The HFile format version to use for new files. Set this to 1 to test backwards-compatibility. The default value of this option should be consistent with FixedFileTrailer.MAX_VERSION.

            Default: 2

            io.storefile.bloom.block.size

            The size in bytes of a single block ("chunk") of a compound Bloom filter. This size is approximate, because Bloom blocks can only be inserted at data block boundaries, and the number of keys per data block varies.

            Default: 131072

            hfile.block.bloom.cacheonwrite

            Enables cache-on-write for inline blocks of a compound Bloom filter.

            Default: false

            hbase.rs.cacheblocksonwrite

            Whether an HFile block should be added to the block cache when the block is finished.

            Default: false

            hbase.rpc.server.engine

            Implementation of org.apache.hadoop.hbase.ipc.RpcServerEngine to be used for server RPC call marshalling.

            Default: org.apache.hadoop.hbase.ipc.ProtobufRpcServerEngine

            hbase.ipc.client.tcpnodelay

            Set no delay on rpc socket connections. See http://docs.oracle.com/javase/1.5.0/docs/api/java/net/Socket.html#getTcpNoDelay()

            Default: true

             
            hbase.master.keytab.file

            HMaster server驗證登錄使用的kerberos keytab 文件路徑。(譯者注:HBase使用Kerberos實現安全)

            默認:

            hbase.master.kerberos.principal

            例如. "hbase/_HOST@EXAMPLE.COM". HMaster運行需要使用 kerberos principal name. principal name 可以在: user/hostname@DOMAIN 中獲取. 如果 "_HOST" 被用做hostname portion,需要使用實際運行的hostname來替代它。

            默認:

            hbase.regionserver.keytab.file

            HRegionServer驗證登錄使用的kerberos keytab 文件路徑。

            默認:

            hbase.regionserver.kerberos.principal

            例如. "hbase/_HOST@EXAMPLE.COM". HRegionServer運行需要使用 kerberos principal name. principal name 可以在: user/hostname@DOMAIN 中獲取. 如果 "_HOST" 被用做hostname portion,需要使用實際運行的hostname來替代它。在這個文件中必須要有一個entry來描述 hbase.regionserver.keytab.file

            默認:

            hadoop.policy.file

            The policy configuration file used by RPC servers to make authorization decisions on client requests. Only used when HBase security is enabled.

            Default: hbase-policy.xml

            hbase.superuser

            List of users or groups (comma-separated), who are allowed full privileges, regardless of stored ACLs, across the cluster. Only used when HBase security is enabled.

            Default:

            hbase.auth.key.update.interval

            The update interval for master key for authentication tokens in servers in milliseconds. Only used when HBase security is enabled.

            Default: 86400000

            hbase.auth.token.max.lifetime

            The maximum lifetime in milliseconds after which an authentication token expires. Only used when HBase security is enabled.

            Default: 604800000

             
            zookeeper.session.timeout

            ZooKeeper 會話超時.HBase把這個值傳遞改zk集群,向他推薦一個會話的最大超時時間。詳見http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions "The client sends a requested timeout, the server responds with the timeout that it can give the client. "。 單位是毫秒

            默認: 180000

            zookeeper.znode.parent

            ZooKeeper中的HBase的根ZNode。所有的HBase的ZooKeeper會用這個目錄配置相對路徑。默認情況下,所有的HBase的ZooKeeper文件路徑是用相對路徑,所以他們會都去這個目錄下面。

            默認: /hbase

            zookeeper.znode.rootserver

            ZNode 保存的 根region的路徑. 這個值是由Master來寫,client和regionserver 來讀的。如果設為一個相對地址,父目錄就是 ${zookeeper.znode.parent}.默認情形下,意味著根region的路徑存儲在/hbase/root-region-server.

            默認: root-region-server


            zookeeper.znode.acl.parent

            Root ZNode for access control lists.

            Default: acl

            hbase.coprocessor.region.classes

            A comma-separated list of Coprocessors that are loaded by default on all tables. For any override coprocessor method, these classes will be called in order. After implementing your own Coprocessor, just put it in HBase's classpath and add the fully qualified class name here. A coprocessor can also be loaded on demand by setting HTableDescriptor.

            Default:

            hbase.coprocessor.master.classes

            A comma-separated list of org.apache.hadoop.hbase.coprocessor.MasterObserver coprocessors that are loaded by default on the active HMaster process. For any implemented coprocessor methods, the listed classes will be called in order. After implementing your own MasterObserver, just put it in HBase's classpath and add the fully qualified class name here.

            Default:

             
            hbase.zookeeper.quorum

            Zookeeper集群的地址列表,用逗號分割。例如:"host1.mydomain.com,host2.mydomain.com,host3.mydomain.com".默認是localhost,是給偽分布式用的。要修改才能在完全分布式的情況下使用。如果在hbase-env.sh設置了HBASE_MANAGES_ZK,這些ZooKeeper節點就會和HBase一起啟動。

            默認: localhost

            hbase.zookeeper.peerport

            ZooKeeper節點使用的端口。詳細參見:http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper

            默認: 2888

            hbase.zookeeper.leaderport

            ZooKeeper用來選擇Leader的端口,詳細參見:http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper

            默認: 3888

            hbase.zookeeper.useMulti

            Instructs HBase to make use of ZooKeeper's multi-update functionality. This allows certain ZooKeeper operations to complete more quickly and prevents some issues with rare Replication failure scenarios (see the release note of HBASE-2611 for an example). IMPORTANT: only set this to true if all ZooKeeper servers in the cluster are on version 3.4+ and will not be downgraded. ZooKeeper versions before 3.4 do not support multi-update and will not fail gracefully if multi-update is invoked (see ZOOKEEPER-1495).

            Default: false

             
            hbase.zookeeper.property.initLimit

            ZooKeeper的zoo.conf中的配置。 初始化synchronization階段的ticks數量限制

            默認: 10

            hbase.zookeeper.property.syncLimit

            ZooKeeper的zoo.conf中的配置。 發送一個請求到獲得承認之間的ticks的數量限制

            默認: 5

            hbase.zookeeper.property.dataDir

            ZooKeeper的zoo.conf中的配置。 快照的存儲位置

            默認: ${hbase.tmp.dir}/zookeeper

            hbase.zookeeper.property.clientPort

            ZooKeeper的zoo.conf中的配置。 客戶端連接的端口

            默認: 2181

            hbase.zookeeper.property.maxClientCnxns

            ZooKeeper的zoo.conf中的配置。 ZooKeeper集群中的單個節點接受的單個Client(以IP區分)的請求的并發數。這個值可以調高一點,防止在單機和偽分布式模式中出問題。

            默認: 300

            hbase.rest.port

            HBase REST server的端口

            默認: 8080

            hbase.rest.readonly

            定義REST server的運行模式。可以設置成如下的值: false: 所有的HTTP請求都是被允許的 - GET/PUT/POST/DELETE. true:只有GET請求是被允許的

            默認: false

            hbase.defaults.for.version.skip

            Set to true to skip the 'hbase.defaults.for.version' check. Setting this to true can be useful in contexts other than the other side of a maven generation; i.e. running in an ide. You'll want to set this boolean to true to avoid seeing the RuntimException complaint: "hbase-default.xml file seems to be for and old version of HBase (\${hbase.version}), this version is X.X.X-SNAPSHOT"

            Default: false

            hbase.coprocessor.abortonerror

            Set to true to cause the hosting server (master or regionserver) to abort if a coprocessor throws a Throwable object that is not IOException or a subclass of IOException. Setting it to true might be useful in development environments where one wants to terminate the server as soon as possible to simplify coprocessor failure analysis.

            Default: false

            hbase.online.schema.update.enable

            Set true to enable online schema changes. This is an experimental feature. There are known issues modifying table schemas at the same time a region split is happening so your table needs to be quiescent or else you have to be running with splits disabled.

            Default: false

            hbase.table.lock.enable

            Set to true to enable locking the table in zookeeper for schema change operations. Table locking from master prevents concurrent schema modifications to corrupt table state.

            Default: true

            dfs.support.append

            Does HDFS allow appends to filesThis is an hdfs config. set in here so the hdfs client will do append support. You must ensure that this config. is true serverside too when running hbase (You will have to restart your cluster after setting it).

            Default: true

            hbase.thrift.minWorkerThreads

            The "core size" of the thread pool. New threads are created on every connection until this many threads are created.

            Default: 16

            hbase.thrift.maxWorkerThreads

            The maximum size of the thread pool. When the pending request queue overflows, new threads are created until their number reaches this number. After that, the server starts dropping connections.

            Default: 1000

            hbase.thrift.maxQueuedRequests

            The maximum number of pending Thrift connections waiting in the queue. If there are no idle threads in the pool, the server queues requests. Only when the queue overflows, new threads are added, up to hbase.thrift.maxQueuedRequests threads.

            Default: 1000

            hbase.offheapcache.percentage

            The amount of off heap space to be allocated towards the experimental off heap cache. If you desire the cache to be disabled, simply set this value to 0.

            Default: 0

            hbase.data.umask.enable

            Enable, if true, that file permissions should be assigned to the files written by the regionserver

            Default: false

            hbase.data.umask

            File permissions that should be used to write data files when hbase.data.umask.enable is true

            Default: 000

            hbase.metrics.showTableName

            Whether to include the prefix "tbl.tablename" in per-column family metrics. If true, for each metric M, per-cf metrics will be reported for tbl.T.cf.CF.M, if false, per-cf metrics will be aggregated by column-family across tables, and reported for cf.CF.M. In both cases, the aggregated metric M across tables and cfs will be reported.

            Default: true

            hbase.metrics.exposeOperationTimes

            Whether to report metrics about time taken performing an operation on the region server. Get, Put, Delete, Increment, and Append can all have their times exposed through Hadoop metrics per CF and per region.

            Default: true

            hbase.master.hfilecleaner.plugins

            A comma-separated list of HFileCleanerDelegate invoked by the HFileCleaner service. These HFiles cleaners are called in order, so put the cleaner that prunes the most files in front. To implement your own HFileCleanerDelegate, just put it in HBase's classpath and add the fully qualified class name here. Always add the above default log cleaners in the list as they will be overwritten in hbase-site.xml.

            Default: org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner

            hbase.regionserver.catalog.timeout

            Timeout value for the Catalog Janitor from the regionserver to META.

            Default: 600000

            hbase.master.catalog.timeout

            Timeout value for the Catalog Janitor from the master to META.

            Default: 600000

            hbase.config.read.zookeeper.config

            Set to true to allow HBaseConfiguration to read the zoo.cfg file for ZooKeeper properties. Switching this to true is not recommended, since the functionality of reading ZK properties from a zoo.cfg file has been deprecated.

            Default: false

            hbase.snapshot.enabled

            Set to true to allow snapshots to be taken / restored / cloned.

            Default: true

            hbase.rest.threads.max

            The maximum number of threads of the REST server thread pool. Threads in the pool are reused to process REST requests. This controls the maximum number of requests processed concurrently. It may help to control the memory used by the REST server to avoid OOM issues. If the thread pool is full, incoming requests will be queued up and wait for some free threads. The default is 100.

            Default: 100

            hbase.rest.threads.min

            The minimum number of threads of the REST server thread pool. The thread pool always has at least these number of threads so the REST server is ready to serve incoming requests. The default is 2.

            Default: 2

             

            2.3.2. hbase-env.sh

            在這個文件里面設置HBase環境變量。比如可以配置JVM啟動的堆大小或者GC的參數。你還可在這里配置HBase的參數,如Log位置,niceness(譯者注:優先級),ssh參數還有pid文件的位置等等。打開文件conf/hbase-env.sh細讀其中的內容。每個選項都是有詳盡的注釋的。你可以在此添加自己的環境變量。

            這個文件的改動系統HBase重啟才能生效。

            2.3.3. log4j.properties

            編輯這個文件可以改變HBase的日志的級別,輪滾策略等等。

            這個文件的改動系統HBase重啟才能生效。 日志級別的更改會影響到HBase UI

            2.3.4. 連接HBase集群的客戶端配置和依賴

            因為HBase的Master有可能轉移,所有客戶端需要訪問ZooKeeper來獲得現在的位置。ZooKeeper會保存這些值。因此客戶端必須知道Zookeeper集群的地址,否則做不了任何事情。通常這個地址存在 hbase-site.xml 里面,客戶端可以從CLASSPATH取出這個文件.

            如果你是使用一個IDE來運行HBase客戶端,你需要將conf/放入你的 classpath,這樣 hbase-site.xml就可以找到了,(或者把hbase-site.xml放到 src/test/resources,這樣測試的時候可以使用).

            HBase客戶端最小化的依賴是 hbase, hadoop, log4j, commons-logging, commons-lang, 和 ZooKeeper ,這些jars 需要能在 CLASSPATH 中找到。

            下面是一個基本的客戶端 hbase-site.xml 例子:

            <?xml version="1.0"?>
            <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
            <configuration>
              <property>
                <name>hbase.zookeeper.quorum</name>
                <value>example1,example2,example3</value>
                <description>The directory shared by region servers.
                </description>
              </property>
            </configuration>
                      

            2.3.4.1. Java客戶端配置

            Java是如何讀到hbase-site.xml 的內容的

            Java客戶端使用的配置信息是被映射在一個HBaseConfiguration 實例中. HBaseConfiguration有一個工廠方法, HBaseConfiguration.create();,運行這個方法的時候,他會去CLASSPATH,下找hbase-site.xml,讀他發現的第一個配置文件的內容。 (這個方法還會去找hbase-default.xml ; hbase.X.X.X.jar里面也會有一個an hbase-default.xml). 不使用任何hbase-site.xml文件直接通過Java代碼注入配置信息也是可以的。例如,你可以用編程的方式設置ZooKeeper信息,只要這樣做:

            Configuration config = HBaseConfiguration.create();
            config.set("hbase.zookeeper.quorum", "localhost");  // Here we are running zookeeper locally

            如果有多ZooKeeper實例,你可以使用逗號列表。(就像在hbase-site.xml 文件中做得一樣). 這個 Configuration 實例會被傳遞到 HTable, 之類的實例里面去.



            2.4. 配置示例

            2.4.1. 簡單的分布式HBase安裝

            這里是一個10節點的HBase的簡單示例,這里的配置都是基本的,節點名為 example0, example1... 一直到 example9 . HBase Master 和 HDFS namenode 運作在同一個節點 example0上. RegionServers 運行在節點 example1-example9. 一個 3-節點 ZooKeeper 集群運行在example1, example2, 和 example3,端口保持默認. ZooKeeper 的數據保存在目錄 /export/zookeeper. 下面我們展示主要的配置文件-- hbase-site.xml, regionservers, 和 hbase-env.sh -- 這些文件可以在 conf目錄找到.

            2.4.1.1. hbase-site.xml

            <?xml version="1.0"?>
            <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
            <configuration>
              <property>
                <name>hbase.zookeeper.quorum</name>
                <value>example1,example2,example3</value>
                <description>The directory shared by RegionServers.
                </description>
              </property>
              <property>
                <name>hbase.zookeeper.property.dataDir</name>
                <value>/export/zookeeper</value>
                <description>Property from ZooKeeper's config zoo.cfg.
                The directory where the snapshot is stored.
                </description>
              </property>
              <property>
                <name>hbase.rootdir</name>
                <value>hdfs://example0:9000/hbase</value>
                <description>The directory shared by RegionServers.
                </description>
              </property>
              <property>
                <name>hbase.cluster.distributed</name>
                <value>true</value>
                <description>The mode the cluster will be in. Possible values are
                  false: standalone and pseudo-distributed setups with managed Zookeeper
                  true: fully-distributed with unmanaged Zookeeper Quorum (see hbase-env.sh)
                </description>
              </property>
            </configuration>
            
                      

            2.4.1.2. regionservers

            這個文件把RegionServer的節點列了下來。在這個例子里面我們讓所有的節點都運行RegionServer,除了第一個節點 example1,它要運行 HBase Master 和 HDFS namenode

                example1
                example3
                example4
                example5
                example6
                example7
                example8
                example9
                      

            2.4.1.3. hbase-env.sh

            下面我們用diff 命令來展示 hbase-env.sh 文件相比默認變化的部分. 我們把HBase的堆內存設置為4G而不是默認的1G.

                
            $ git diff hbase-env.sh
            diff --git a/conf/hbase-env.sh b/conf/hbase-env.sh
            index e70ebc6..96f8c27 100644
            --- a/conf/hbase-env.sh
            +++ b/conf/hbase-env.sh
            @@ -31,7 +31,7 @@ export JAVA_HOME=/usr/lib//jvm/java-6-sun/
             # export HBASE_CLASSPATH=
             
             # The maximum amount of heap to use, in MB. Default is 1000.
            -# export HBASE_HEAPSIZE=1000
            +export HBASE_HEAPSIZE=4096
             
             # Extra Java runtime options.
             # Below are what we set by default.  May only work with SUN JVM.
            
                      

            你可以使用 rsync 來同步 conf 文件夾到你的整個集群.



            2.5. 重要的配置

            下面我們會列舉重要 的配置. 這個章節講述必須的配置和那些值得一看的配置。(譯者注:淘寶的博客也有本章節的內容,HBase性能調優,很詳盡)。

            2.5.1. 必須的配置

            參考 Section 2.2, “操作系統” 和 Section 2.3, “Hadoop” 節.

            2.5.2. 推薦配置

            2.5.2.1. zookeeper.session.timeout

            這個默認值是3分鐘。這意味著一旦一個server宕掉了,Master至少需要3分鐘才能察覺到宕機,開始恢復。你可能希望將這個超時調短,這樣Master就能更快的察覺到了。在你調這個值之前,你需要確認你的JVM的GC參數,否則一個長時間的GC操作就可能導致超時。(當一個RegionServer在運行一個長時間的GC的時候,你可能想要重啟并恢復它).

            要想改變這個配置,可以編輯 hbase-site.xml, 將配置部署到全部集群,然后重啟。

            我們之所以把這個值調的很高,是因為我們不想一天到晚在論壇里回答新手的問題。“為什么我在執行一個大規模數據導入的時候Region Server死掉啦”,通常這樣的問題是因為長時間的GC操作引起的,他們的JVM沒有調優。我們是這樣想的,如果一個人對HBase不很熟悉,不能期望他知道所有,打擊他的自信心。等到他逐漸熟悉了,他就可以自己調這個參數了。

            2.5.2.2.  ZooKeeper 實例個數

            參考 Section 2.5, “ZooKeeper”.

            2.5.2.3. hbase.regionserver.handler.count

            這個設置決定了處理用戶請求的線程數量。默認是10,這個值設的比較小,主要是為了預防用戶用一個比較大的寫緩沖,然后還有很多客戶端并發,這樣region servers會垮掉。有經驗的做法是,當請求內容很大(上MB,如大puts, 使用緩存的scans)的時候,把這個值放低。請求內容較小的時候(gets, 小puts, ICVs, deletes),把這個值放大。

            當客戶端的請求內容很小的時候,把這個值設置的和最大客戶端數量一樣是很安全的。一個典型的例子就是一個給網站服務的集群,put操作一般不會緩沖,絕大多數的操作是get操作。

            把這個值放大的危險之處在于,把所有的Put操作緩沖意味著對內存有很大的壓力,甚至會導致OutOfMemory.一個運行在內存不足的機器的RegionServer會頻繁的觸發GC操作,漸漸就能感受到停頓。(因為所有請求內容所占用的內存不管GC執行幾遍也是不能回收的)。一段時間后,集群也會受到影響,因為所有的指向這個region的請求都會變慢。這樣就會拖累集群,加劇了這個問題。

            你可能會對handler太多或太少有感覺,可以通過 Section 12.2.2.1, “啟用 RPC級 日志” ,在單個RegionServer啟動log并查看log末尾 (請求隊列消耗內存)。

            2.5.2.4. 大內存機器的配置

            HBase有一個合理的保守的配置,這樣可以運作在所有的機器上。如果你有臺大內存的集群-HBase有8G或者更大的heap,接下來的配置可能會幫助你. TODO.

            2.5.2.5. 壓縮

            應該考慮啟用ColumnFamily 壓縮。有好幾個選項,通過降低存儲文件大小以降低IO,降低消耗且大多情況下提高性能。

            參考 Appendix C,  HBase壓縮  獲取更多信息.

            2.5.2.6. 較大 Regions

            更大的Region可以使你集群上的Region的總數量較少。 一般來言,更少的Region可以使你的集群運行更加流暢。(你可以自己隨時手工將大Region切割,這樣單個熱點Region就會被分布在集群的更多節點上)。

            較少的Region較好。一般每個RegionServer在20到小幾百之間。 調整Region大小以適合該數字。

             

            0.90.x 版本, 默認情況下單個Region是256MB。Region 大小的上界是 4Gb. 0.92.x 版本, 由于 HFile v2 已經將Region大小支持得大很多, (如, 20Gb).

            可能需要實驗,基于硬件和應用需要進行配置。

            可以調整hbase-site.xml中的 hbase.hregion.max.filesize屬性. RegionSize 也可以基于每個表設置:  HTableDescriptor.

            2.5.2.7. 管理 Splitting

            除了讓HBase自動切割你的Region,你也可以手動切割。 [12] 隨著數據量的增大,splite會被持續執行。如果你需要知道你現在有幾個region,比如長時間的debug或者做調優,你需要手動切割。通過跟蹤日志來了解region級的問題是很難的,因為他在不停的切割和重命名。data offlineing bug和未知量的region會讓你沒有辦法。如果一個 HLog 或者 StoreFile由于一個奇怪的bug,HBase沒有執行它。等到一天之后,你才發現這個問題,你可以確保現在的regions和那個時候的一樣,這樣你就可以restore或者replay這些數據。你還可以調優你的合并算法。如果數據是均勻的,隨著數據增長,很容易導致split / compaction瘋狂的運行。因為所有的region都是差不多大的。用手的切割,你就可以交錯執行定時的合并和切割操作,降低IO負載。

            為什么我關閉自動split呢?因為自動的splite是配置文件中的 hbase.hregion.max.filesize決定的. 你把它設置成Long.MAX_VALUE是不推薦的做法,要是你忘記了手工切割怎么辦.推薦的做法是設置成100GB,一旦到達這樣的值,至少需要一個小時執行 major compactions。

            那什么是最佳的在pre-splite regions的數量呢。這個決定于你的應用程序了。你可以先從低的開始,比如每個server10個pre-splite regions.然后花時間觀察數據增長。有太少的region至少比出錯好,你可以之后再rolling split.一個更復雜的答案是這個值是取決于你的region中的最大的storefile。隨著數據的增大,這個也會跟著增大。 你可以當這個文件足夠大的時候,用一個定時的操作使用Store的合并選擇算法(compact selection algorithm)來僅合并這一個HStore。如果你不這樣做,這個算法會啟動一個 major compactions,很多region會受到影響,你的集群會瘋狂的運行。需要注意的是,這樣的瘋狂合并操作是數據增長造成的,而不是手動分割操作決定的。

            如果你 pre-split 導致 regions 很小,你可以通過配置HConstants.MAJOR_COMPACTION_PERIOD把你的major compaction參數調大

            如果你的數據變得太大,可以使用org.apache.hadoop.hbase.util.RegionSplitter 腳本來執行針對全部集群的一個網絡IO安全的rolling split操作。

             

            2.5.2.8. 管理 Compactions

            通常管理技術是手動管理主緊縮(major compactions), 而不是讓HBase 來做。 缺省HConstants.MAJOR_COMPACTION_PERIOD 是一天。主緊縮可能強行進行,在你并不太希望發生的時候——特別是在一個繁忙系統。關閉自動主緊縮,設置該值為0.

            重點強調,主緊縮對存儲文件(StoreFile)清理是絕對必要的。唯一變量是發生的時間。可以通過HBase shell進行管理,或通過 HBaseAdmin.

            更多信息關于緊縮和緊縮文件選擇過程,參考 Section 9.7.5.5, “緊縮”

            2.5.2.9.  預測執行 (Speculative Execution)

            MapReduce任務的預測執行缺省是打開的,HBase集群一般建議在系統級關閉預測執行,除非在某種特殊情況下需要打開,此時可以每任務配置。設置mapred.map.tasks.speculative.execution 和 mapred.reduce.tasks.speculative.execution 為 false.

            2.5.3. 其他配置

            2.5.3.1. 負載均衡

            負載均衡器(LoadBalancer)是在主服務器上運行的定期操作,以重新分布集群區域。通過hbase.balancer.period 設置,缺省值300000 (5 分鐘).

            參考 Section 9.5.4.1, “負載均衡” 獲取關于負載均衡器( LoadBalancer )的更多信息。

            2.5.3.2. 禁止塊緩存(Blockcache)

            不要關閉塊緩存 (通過hbase.block.cache.size 為 0 來設置)。當前如果關閉塊緩存會很不好,因為區域服務器會花很多時間不停加載hfile指數。如果工作集如此配置塊緩存沒有好處,最少應保證hfile指數保存在塊緩存內的大小(可以通過查詢區域服務器的UI,得到大致的數值。可以看到網頁的上方有塊指數值統計).

            2.5.3.3. Nagle算法 或小包問題

            如果操作HBase時看到大量40ms左右的偶然延時,嘗試Nagles配置。如,參考用戶郵件列表線索, Inconsistent scan performance with caching set to 1 ,該議題在其中啟用tcpNoDelay (譯者注,本英文原文notcpdelay有誤)提高了掃描速度。你也可以查看該文檔的尾部圖表:HBASE-7008 Set scanner caching to a better default  (xie liang),我們的Lars Hofhansl 嘗試了各種不同的數據大小,Nagle打開或關閉的測量結果。




             

            [1] Be careful editing XML. Make sure you close all elements. Run your file through xmllint or similar to ensure well-formedness of your document after an edit session.

            [2] The hadoop-dns-checker tool can be used to verify DNS is working correctly on the cluster. The project README file provides detailed instructions on usage.

            [3] 參考 Jack Levin's major hdfs issues note up on the user list.

            [4] The requirement that a database requires upping of system limits is not peculiar to HBase. 參考 for example the section Setting Shell Limits for the Oracle User inShort Guide to install Oracle 10 on Linux.

            [5] A useful read setting config on you hadoop cluster is Aaron Kimballs' Configuration Parameters: What can you just ignore?

            [6] <title>On Hadoop Versions</title>

            [6] The Cloudera blog post An update on Apache Hadoop 1.0 by Charles Zedlweski has a nice exposition on how all the Hadoop versions relate. Its worth checking out if you are having trouble making sense of the Hadoop version morass.

            [7] Until recently only the branch-0.20-append branch had a working sync but no official release was ever made from this branch. You had to build it yourself. Michael Noll wrote a detailed blog, Building an Hadoop 0.20.x version for HBase 0.90.2, on how to build an Hadoop from branch-0.20-append. Recommended.

            [8] Praveen Kumar has written a complimentary article, Building Hadoop and HBase for HBase Maven application development.

            [9] dfs.support.append

            [10] 參考 Hadoop HDFS: Deceived by Xciever for an informative rant on xceivering.

            [11] The pseudo-distributed vs fully-distributed nomenclature comes from Hadoop.

            [12] 參考 Section 2.4.2.1.2, “Pseudo-distributed Extras” for notes on how to start extra Masters and RegionServers when running pseudo-distributed.

            [13] 對 ZooKeeper 全部配置,參考ZooKeeper 的zoo.cfg. HBase 沒有包含 zoo.cfg ,所以需要瀏覽合適的獨立ZooKeeper下載版本的 conf 目錄找到。

            [14] What follows is taken from the javadoc at the head of the org.apache.hadoop.hbase.util.RegionSplitter tool added to HBase post-0.90.0 release.

             

            Chapter 3. 升級

            不能跳過主要版本升級。如果想從0.20.x 升級到 0.92.x,必須從0.20.x 升級到 0.90.x ,再從0.90.x 升級到 0.92.x.

            參見 Section 2, “配置”, 需要特別注意有關Hadoop 版本的信息.

            3.1. 從 0.94.x 升級到 0.96.x

            The Singularity

            You will have to stop your old 0.94 cluster completely to upgrade. If you are replicating between clusters, both clusters will have to go down to upgrade. Make sure it is a clean shutdown so there are no WAL files laying around (TODO: Can 0.96 read 0.94 WAL files?). Make sure zookeeper is cleared of state. All clients must be upgraded to 0.96 too.

            The API has changed in a few areas; in particular how you use coprocessors (TODO: MapReduce too?)

            3.2. 從 0.92.x 升級到 0.94.x

            0.92 和 0.94 接口兼容,可平滑升級。

             

            3.3. 從 0.90.x 到 0.92.x 升級

            升級指引

            You will find that 0.92.0 runs a little differently to 0.90.x releases. Here are a few things to watch out for upgrading from 0.90.x to 0.92.0.

             

            If you've not patience, here are the important things to know upgrading.

            1. Once you upgrade, you can’t go back.
            2. MSLAB is on by default. Watch that heap usage if you have a lot of regions.
            3. Distributed splitting is on by defaul. It should make region server failover faster.
            4. There’s a separate tarball for security.
            5. If -XX:MaxDirectMemorySize is set in your hbase-env.sh, it’s going to enable the experimental off-heap cache (You may not want this).

            3.3.1. 不可回退!

            To move to 0.92.0, all you need to do is shutdown your cluster, replace your hbase 0.90.x with hbase 0.92.0 binaries (be sure you clear out all 0.90.x instances) and restart (You cannot do a rolling restart from 0.90.x to 0.92.x -- you must restart). On startup, the .META. table content is rewritten removing the table schema from the info:regioninfo column. Also, any flushes done post first startup will write out data in the new 0.92.0 file format, HFile V2. This means you cannot go back to 0.90.x once you’ve started HBase 0.92.0 over your HBase data directory.

            3.3.2. MSLAB 缺省啟用

            In 0.92.0, the hbase.hregion.memstore.mslab.enabled flag is set to true (參考 Section 11.3.1.1, “Long GC pauses”). In 0.90.x it was false. When it is enabled, memstores will step allocate memory in MSLAB 2MB chunks even if the memstore has zero or just a few small elements. This is fine usually but if you had lots of regions per regionserver in a 0.90.x cluster (and MSLAB was off), you may find yourself OOME'ing on upgrade because the thousands of regions * number of column families * 2MB MSLAB (at a minimum) puts your heap over the top. Set hbase.hregion.memstore.mslab.enabled to false or set the MSLAB size down from 2MB by setting hbase.hregion.memstore.mslab.chunksize to something less.

            3.3.3. 分布式分割缺省啟用

            Previous, WAL logs on crash were split by the Master alone. In 0.92.0, log splitting is done by the cluster (參考 “HBASE-1364 [performance] Distributed splitting of regionserver commit logs”). This should cut down significantly on the amount of time it takes splitting logs and getting regions back online again.

            3.3.4. 內存計算改變

            In 0.92.0, Appendix E, HFile format version 2 indices and bloom filters take up residence in the same LRU used caching blocks that come from the filesystem. In 0.90.x, the HFile v1 indices lived outside of the LRU so they took up space even if the index was on a ‘cold’ file, one that wasn’t being actively used. With the indices now in the LRU, you may find you have less space for block caching. Adjust your block cache accordingly. 參考 the Section 9.6.4, “Block Cache” for more detail. The block size default size has been changed in 0.92.0 from 0.2 (20 percent of heap) to 0.25.

            3.3.5.  可用 Hadoop 版本

            Run 0.92.0 on Hadoop 1.0.x (or CDH3u3 when it ships). The performance benefits are worth making the move. Otherwise, our Hadoop prescription is as it has been; you need an Hadoop that supports a working sync. 參考 Section 2.3, “Hadoop”.

            If running on Hadoop 1.0.x (or CDH3u3), enable local read. 參考 Practical Caching presentation for ruminations on the performance benefits ‘going local’ (and for how to enable local reads).

            3.3.6. HBase 0.92.0 帶 ZooKeeper 3.4.2

            If you can, upgrade your zookeeper. If you can’t, 3.4.2 clients should work against 3.3.X ensembles (HBase makes use of 3.4.2 API).

            3.3.7. 在線切換缺省關閉

            In 0.92.0, we’ve added an experimental online schema alter facility (參考 hbase.online.schema.update.enable). Its off by default. Enable it at your own risk. Online alter and splitting tables do not play well together so be sure your cluster quiescent using this feature (for now).

            3.3.8. WebUI

            The webui has had a few additions made in 0.92.0. It now shows a list of the regions currently transitioning, recent compactions/flushes, and a process list of running processes (usually empty if all is well and requests are being handled promptly). Other additions including requests by region, a debugging servlet dump, etc.

            3.3.9. 安全 tarball

            我們發布兩個tarball: 安全和非安全 HBase. 如何設置安全HBase的文檔正在制定中。

            3.3.10. 試驗離堆(off-heap)緩存

            (譯者注:on-heap和off-heap是Terracotta 公司提出的概念。on-heap指java對象在GC內存儲管理,效率較高,但GC只能管理2G內存,有時成為性能瓶頸。off-heap又叫BigMemory ,是JVM的GC機制的替代,在GC外存儲,100倍速于DiskStore,cache量目前(2012年底)達到350GB)

            A new cache was contributed to 0.92.0 to act as a solution between using the “on-heap” cache which is the current LRU cache the region servers have and the operating system cache which is out of our control. To enable, set “-XX:MaxDirectMemorySize” in hbase-env.sh to the value for maximum direct memory size and specify hbase.offheapcache.percentage in hbase-site.xml with the percentage that you want to dedicate to off-heap cache. This should only be set for servers and not for clients. Use at your own risk. See this blog post for additional information on this new experimental feature: http://www.cloudera.com/blog/2012/01/caching-in-hbase-slabcache/

            3.3.11. HBase 復制的變動

            0.92.0 adds two new features: multi-slave and multi-master replication. The way to enable this is the same as adding a new peer, so in order to have multi-master you would just run add_peer for each cluster that acts as a master to the other slave clusters. Collisions are handled at the timestamp level which may or may not be what you want, this needs to be evaluated on a per use case basis. Replication is still experimental in 0.92 and is disabled by default, run it at your own risk.

            3.3.12. 對OOME ,RegionServer 現在退出

            If an OOME, we now have the JVM kill -9 the regionserver process so it goes down fast. Previous, a RegionServer might stick around after incurring an OOME limping along in some wounded state. To disable this facility, and recommend you leave it in place, you’d need to edit the bin/hbase file. Look for the addition of the -XX:OnOutOfMemoryError="kill -9 %p" arguments (參考 [HBASE-4769] - ‘Abort RegionServer Immediately on OOME’)

            3.3.13. HFile V2 和 “更大, 更少” 趨勢

            0.92.0 stores data in a new format, Appendix E, HFile format version 2. As HBase runs, it will move all your data from HFile v1 to HFile v2 format. This auto-migration will run in the background as flushes and compactions run. HFile V2 allows HBase run with larger regions/files. In fact, we encourage that all HBasers going forward tend toward Facebook axiom #1, run with larger, fewer regions. If you have lots of regions now -- more than 100s per host -- you should look into setting your region size up after you move to 0.92.0 (In 0.92.0, default size is not 1G, up from 256M), and then running online merge tool (參考 “HBASE-1621 merge tool should work on online cluster, but disabled table”).

             

            3.4. 從HBase 0.20.x or 0.89.x 升級到 HBase 0.90.x

            0.90.x 版本的HBase可以在 HBase 0.20.x 或者 HBase 0.89.x的數據上啟動. 不需要轉換數據文件, HBase 0.89.x 和 0.90.x 的region目錄名是不一樣的 -- 老版本用md5 hash 而不是jenkins hash 來命名region-- 這就意味著,一旦啟動,再也不能回退到 HBase 0.20.x.

            在升級的時候,一定要將hbase-default.xml 從你的 conf目錄刪掉。 0.20.x 版本的配置對于 0.90.x HBase不是最佳的. hbase-default.xml 現在已經被打包在 HBase jar 里面了. 如果你想看看這個文件內容,你可以在src目錄下 src/main/resources/hbase-default.xml 或者在 Section 2.31.1, “HBase 默認配置”看到.

            最后,如果從0.20.x升級,需要在shell里檢查 .META. schema . 過去,我們推薦用戶使用16KB的 MEMSTORE_FLUSHSIZE. 在shell中運行 hbase> scan '-ROOT-'. 會顯示當前的.META. schema. 檢查 MEMSTORE_FLUSHSIZE 的大小. 看看是不是 16KB (16384)如果是的話,你需要修改它(默認的值是 64MB (67108864)) 運行腳本 bin/set_meta_memstore_size.rb. 這個腳本會修改 .META. schema. 如果不運行的話,集群會比較慢[15] .



             

            Chapter 4.  HBase Shell

            HBase Shell is 在(J)Ruby的IRB的基礎上加上了HBase的命令。任何你可以在IRB里做的事情都可在在HBase Shell中做。

            你可以這樣來運行HBase Shell:

            $ ./bin/hbase shell

            輸入 help 就會返回Shell的命令列表和選項。可以看看在Help文檔尾部的關于如何輸入變量和選項。尤其要注意的是表名,行,列名必須要加引號。

            參見 Section 1.2.3, “Shell 練習”可以看到Shell的基本使用例子。

            4.1. 使用腳本

            如果要使用腳本,可以看HBase的bin 目錄.在里面找到后綴為 *.rb的腳本.要想運行這個腳本,要這樣

            $ ./bin/hbase org.jruby.Main PATH_TO_SCRIPT

            就可以了

            4.2. Shell 技巧

            4.2.1. irbrc

            可以在你自己的Home目錄下創建一個.irbrc文件. 在這個文件里加入自定義的命令。有一個有用的命令就是記錄命令歷史,這樣你就可以把你的命令保存起來。

                                    $ more .irbrc
                                    require 'irb/ext/save-history'
                                    IRB.conf[:SAVE_HISTORY] = 100
                                    IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"

            可以參見 ruby 關于 .irbrc 的文檔來學習更多的關于IRB的配置方法。

            4.2.2. LOG 時間轉換

            可以將日期'08/08/16 20:56:29'從hbase log 轉換成一個 timestamp, 操作如下:

                                hbase(main):021:0> import java.text.SimpleDateFormat
                                hbase(main):022:0> import java.text.ParsePosition
                                hbase(main):023:0> SimpleDateFormat.new("yy/MM/dd HH:mm:ss").parse("08/08/16 20:56:29", ParsePosition.new(0)).getTime() => 1218920189000

            也可以逆過來操作。

                                hbase(main):021:0> import java.util.Date
                                hbase(main):022:0> Date.new(1218920189000).toString() => "Sat Aug 16 20:56:29 UTC 2008"

            要想把日期格式和HBase log格式完全相同,可以參見文檔 SimpleDateFormat.

            4.2.3. 調試

            4.2.3.1. Shell 切換成debug 模式

            你可以將shell切換成debug模式。這樣可以看到更多的信息。 -- 例如可以看到命令異常的stack trace:

            hbase> debug <RETURN>

            4.2.3.2. DEBUG log level

            想要在shell中看到 DEBUG 級別的 logging ,可以在啟動的時候加上 -d 參數.

            $ ./bin/hbase shell -d

            Chapter 5. 數據模型

            簡單來說,應用程序是以表的方式在HBase存儲數據的。表是由行和列構成的,所有的列是從屬于某一個列族的。行和列的交叉點稱之為cell,cell是版本化的。cell的內容是不可分割的字節數組。

            表的行鍵也是一段字節數組,所以任何東西都可以保存進去,不論是字符串或者數字。HBase的表是按key排序的,排序方式之針對字節的。所有的表都必須要有主鍵-key.

            5.1. 概念視圖

            下面是根據BigTable 論文稍加修改的例子。 有一個名為webtable的表,包含兩個列族:contentsanchor.在這個例子里面,anchor有兩個列 (anchor:cssnsi.com, anchor:my.look.ca),contents僅有一列(contents:html)

            列名

            一個列名是由它的列族前綴和修飾符(qualifier)連接而成。例如列contents:html是列族 contents加冒號(:)加 修飾符 html組成的。

            Table 5.1. 表 webtable

            Row Key Time Stamp ColumnFamily contents ColumnFamily anchor
            "com.cnn.www" t9   anchor:cnnsi.com = "CNN"
            "com.cnn.www" t8   anchor:my.look.ca = "CNN.com"
            "com.cnn.www" t6 contents:html = "<html>..."  
            "com.cnn.www" t5 contents:html = "<html>..."  
            "com.cnn.www" t3 contents:html = "<html>..."  


            5.2. 物理視圖

            盡管在概念視圖里,表可以被看成是一個稀疏的行的集合。但在物理上,它的是區分列族 存儲的。新的columns可以不經過聲明直接加入一個列族.

            Table 5.2. ColumnFamily anchor

            Row Key Time Stamp Column Family anchor
            "com.cnn.www" t9 anchor:cnnsi.com = "CNN"
            "com.cnn.www" t8 anchor:my.look.ca = "CNN.com"


            Table 5.3. ColumnFamily contents

            Row Key Time Stamp ColumnFamily "contents:"
            "com.cnn.www" t6 contents:html = "<html>..."
            "com.cnn.www" t5 contents:html = "<html>..."
            "com.cnn.www" t3 contents:html = "<html>..."


            值得注意的是在上面的概念視圖中空白cell在物理上是不存儲的,因為根本沒有必要存儲。因此若一個請求為要獲取t8時間的contents:html,他的結果就是空。相似的,若請求為獲取t9時間的anchor:my.look.ca,結果也是空。但是,如果不指明時間,將會返回最新時間的行,每個最新的都會返回。例如,如果請求為獲取行鍵為"com.cnn.www",沒有指明時間戳的話,活動的結果是t6下的contents:html,t9下的anchor:cnnsi.comt8anchor:my.look.ca

            For more information about the internals of how HBase stores data, see Section 9.7, “Regions”.

            5.3. 表

            表是在schema聲明的時候定義的。

            5.4. 行

            行鍵是不可分割的字節數組。行是按字典排序由低到高存儲在表中的。一個空的數組是用來標識表空間的起始或者結尾。

            5.5. 列族

            在HBase是列族一些列的集合。一個列族所有列成員是有著相同的前綴。比如,列courses:historycourses:math都是 列族 courses的成員.冒號(:)是列族的分隔符,用來區分前綴和列名。column 前綴必須是可打印的字符,剩下的部分(稱為qualify),可以又任意字節數組組成。列族必須在表建立的時候聲明。column就不需要了,隨時可以新建。

            在物理上,一個的列族成員在文件系統上都是存儲在一起。因為存儲優化都是針對列族級別的,這就意味著,一個colimn family的所有成員的是用相同的方式訪問的。

            5.6. Cells

            A {row, column, version} 元組就是一個HBase中的一個 cell。Cell的內容是不可分割的字節數組。

            5.7. 數據模型操作

            四個主要的數據模型操作是 Get, Put, Scan, 和 Delete. 通過 HTable 實例進行操作.

            5.7.1. Get

            Get 返回特定行的屬性。 Gets 通過 HTable.get 執行。

            5.7.2. Put

            Put 要么向表增加新行 (如果key是新的) 或更新行 (如果key已經存在)。 Puts 通過 HTable.put (writeBuffer) 或 HTable.batch (non-writeBuffer)執行。

            5.7.3. Scans

            Scan 允許多行特定屬性迭代。

            下面是一個在 HTable 表實例上的示例。 假設表有幾行鍵值為 "row1", "row2", "row3", 還有一些行有鍵值 "abc1", "abc2", 和 "abc3". 下面的示例展示startRow 和 stopRow 可以應用到一個Scan 實例,以返回"row"打頭的行。

            HTable htable = ...      // instantiate HTable
                
            Scan scan = new Scan();
            scan.addColumn(Bytes.toBytes("cf"),Bytes.toBytes("attr"));
            scan.setStartRow( Bytes.toBytes("row"));                   // start key is inclusive
            scan.setStopRow( Bytes.toBytes("row" +  (char)0));  // stop key is exclusive
            ResultScanner rs = htable.getScanner(scan);
            try {
              for (Result r = rs.next(); r != null; r = rs.next()) {
              // process result...
            } finally {
              rs.close();  // always close the ResultScanner!
            }
            

            5.7.4. Delete

            Delete 從表中刪除一行. 刪除通過HTable.delete 執行。

            HBase 沒有修改數據的合適方法。所以通過創建名為墓碑(tombstones)的新標志進行處理。這些墓碑和死去的值,在主緊縮時清除。

            參考 Section 5.8.1.5, “Delete” 獲取刪除列版本的更多信息。參考Section 9.7.5.5, “Compaction” 獲取更多有關緊縮的信息。

            5.8. 版本

            一個 {row, column, version} 元組是HBase中的一個單元(cell).但是有可能會有很多的單元的行和列是相同的,可以使用版本來區分不同的單元.

            rows和column key是用字節數組表示的,version則是用一個長整型表示。這個long的值使用 java.util.Date.getTime() 或者 System.currentTimeMillis()產生的。這就意味著他的含義是“當前時間和1970-01-01 UTC的時間差,單位毫秒。”

            在HBase中,版本是按倒序排列的,因此當讀取這個文件的時候,最先找到的是最近的版本。

            有些人不是很理解HBase單元(cell)的意思。一個常見的問題是:

            • 如果有多個包含版本寫操作同時發起,HBase會保存全部還是會保持最新的一個?[16]

            • 可以發起包含版本的寫操作,但是他們的版本順序和操作順序相反嗎?[17]

            下面我們介紹下在HBase中版本是如何工作的。[18].

            5.8.1. HBase的操作(包含版本操作)

            在這一章我們來仔細看看在HBase的各個主要操作中版本起到了什么作用。

            5.8.1.1. Get/Scan

            Gets實在Scan的基礎上實現的。可以詳細參見下面的討論 Get 同樣可以用 Scan來描述.

            默認情況下,如果你沒有指定版本,當你使用Get操作的時候,會返回最近版本的Cell(該Cell可能是最新寫入的,但不能保證)。默認的操作可以這樣修改:

            • 如果想要返回返回兩個以上的把版本,參見Get.setMaxVersions()

            • 如果想要返回的版本不只是最近的,參見 Get.setTimeRange()

              要向查詢的最新版本要小于或等于給定的這個值,這就意味著給定的'最近'的值可以是某一個時間點。可以使用0到你想要的時間來設置,還要把max versions設置為1.

            5.8.1.2. 默認 Get 例子

            下面的Get操作會只獲得最新的一個版本。

                    Get get = new Get(Bytes.toBytes("row1"));
                    Result r = htable.get(get);
                    byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns current version of value          

            5.8.1.3. 含有的版本的Get例子

            下面的Get操作會獲得最近的3個版本。

                    Get get = new Get(Bytes.toBytes("row1"));
                    get.setMaxVersions(3);  // will return last 3 versions of row
                    Result r = htable.get(get);
                    byte[] b = r.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns current version of value
                    List<KeyValue> kv = r.getColumn(Bytes.toBytes("cf"), Bytes.toBytes("attr"));  // returns all versions of this column       
                                

            5.8.1.4. Put

            一個Put操作會給一個cell,創建一個版本,默認使用當前時間戳,當然你也可以自己設置時間戳。這就意味著你可以把時間設置在過去或者未來,或者隨意使用一個Long值。

            要想覆蓋一個現有的值,就意味著你的row,column和版本必須完全相等。

            5.8.1.4.1. 不指明版本的例子

            下面的Put操作不指明版本,所以HBase會用當前時間作為版本。

                      Put put = new Put(Bytes.toBytes(row));
                      put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), Bytes.toBytes( data));
                      htable.put(put);
                                

            5.8.1.4.2. 指明版本的例子

            下面的Put操作,指明了版本。

                      Put put = new Put( Bytes.toBytes(row ));
                      long explicitTimeInMs = 555;  // just an example
                      put.add(Bytes.toBytes("cf"), Bytes.toBytes("attr1"), explicitTimeInMs, Bytes.toBytes(data));
                      htable.put(put);
                                

            5.8.1.5. Delete

            有三種不同類型的內部刪除標記  [19]:

            • Delete: 刪除列的指定版本.

            • Delete column: 刪除列的所有版本.

            • Delete family: 刪除特定列族所有列

            當刪除一行,HBase將內部對每個列族創建墓碑(非每個單獨列)。

            刪除操作的實現是創建一個墓碑標記。例如,我們想要刪除一個版本,或者默認是currentTimeMillis。就意味著“刪除比這個版本更早的所有版本”.HBase不會去改那些數據,數據不會立即從文件中刪除。他使用刪除標記來屏蔽掉這些值。[20]若你知道的版本比數據中的版本晚,就意味著這一行中的所有數據都會被刪除。

            參考 Section 9.7.5.4, “KeyValue” 獲取內部 KeyValue 格式更多信息。

            5.8.2. 現有的限制

            關于版本還有一些bug(或者稱之為未實現的功能),計劃在下個版本實現。

            5.8.2.1. 刪除標記誤標新Put 的數據

            刪除標記操作可能會標記其后put的數據。[21]記住,當寫下一個墓碑標記后,只有下一個主緊縮操作發起之后,墓碑才會清除。假設你刪除所有<= 時間T的數據。但之后,你又執行了一個Put操作,時間戳<= T。就算這個Put發生在刪除操作之后,他的數據也打上了墓碑標記。這個Put并不會失敗,但你做Get操作時,會注意到Put沒有產生影響。只有一個主緊縮執行后,一切才會恢復正常。如果你的Put操作一直使用升序的版本,這個問題不會有影響。但是即使你不關心時間,也可能出現該情況。只需刪除和插入迅速相互跟隨,就有機會在同一毫秒中遇到。

            5.8.2.2. 主緊縮改變查詢的結果

            “設想一下,你一個cell有三個版本t1,t2和t3。你的maximun-version設置是2.當你請求獲取全部版本的時候,只會返回兩個,t2和t3。如果你將t2和t3刪除,就會返回t1。但是如果在刪除之前,發生了major compaction操作,那么什么值都不好返回了。[22]


            5.9. 排序

            所有數據模型操作 HBase 返回排序的數據。先是行,再是列族,然后是列修飾(column qualifier), 最后是時間戳(反向排序,所以最新的在前).

            5.10. 列的元數據

            對列族,沒有內部的KeyValue之外的元數據保存。這樣,HBase不僅在一行中支持很多列,而且支持行之間不同的列。 由你自己負責跟蹤列名。

            唯一獲取列族的完整列名的方法是處理所有行。HBase內部保存數據更多信息,請參考 Section 9.7.5.4, “KeyValue”.

            5.11. 聯合查詢(Join)

            HBase是否支持聯合是一個網上常問問題。簡單來說 : 不支持。至少不想傳統RDBMS那樣支持(如 SQL中帶 equi-joins 或 outer-joins). 正如本章描述的,讀數據模型是 Get 和 Scan.

            但并不表示等價聯合不能在應用程序中支持,只是必須自己做。 兩種方法,要么指示要寫到HBase的數據,要么查詢表并在應用或MapReduce代碼中做聯合(如 RDBMS所展示,有幾種步驟來實現,依賴于表的大小。如 nested loops vs. hash-joins). 哪個更好?依賴于你準備做什么,所以沒有一個單一的回答適合所有方面。

            5.12. ACID

            參考 ACID Semantics. Lars Hofhansl 也在 ACID in HBase上寫了說明.

             


            [16] 目前,只有最新的那個是可以獲取到的。.

            [17] 可以

            [18] 參考 HBASE-2406 for discussion of HBase versions. Bending time in HBase makes for a good read on the version, or time, dimension in HBase. It has more detail on versioning than is provided here. As of this writing, the limiitation Overwriting values at existing timestamps mentioned in the article no longer holds in HBase. This section is basically a synopsis of this article by Bruno Dumon.

            [19] 參考 Lars Hofhansl's blog for discussion of his attempt adding another, Scanning in HBase: Prefix Delete Marker

            [20] 當HBase執行一次major compaction,標記刪除的數據會被實際的刪除,刪除標記也會被刪除。

            [22] 參考垃圾收集: Bending time in HBase

             

            Chapter 6. HBase 的 Schema 設計

            一份關于各種NSQL數據庫的優點和缺點的通用介紹,就是 Ian Varley的博士論文, No Relation: The Mixed Blessings of Non-Relational Databases。 推薦。也可閱讀 Section 9.7.5.4, “KeyValue” ,了解HBase如何內部保存數據。

            6.1.  模式(Schema) 創建

            可以使用Chapter 4, HBase Shell 或Java API的HBaseAdmin來創建和編輯HBase的模式。

            表必須禁用以修改列族,如:

            Configuration config = HBaseConfiguration.create();  
            HBaseAdmin admin = new HBaseAdmin(conf);    
            String table = "myTable";
            
            admin.disableTable(table);           
            
            HColumnDescriptor cf1 = ...;
            admin.addColumn(table, cf1);      // adding new ColumnFamily
            HColumnDescriptor cf2 = ...;
            admin.modifyColumn(table, cf2);    // modifying existing ColumnFamily
            
            admin.enableTable(table);                
                  
            參考 Section 2.3.4, “Client configuration and dependencies connecting to an HBase cluster” ,獲取更多配置客戶端連接的信息。

            注意: 0.92.x 支持在線修改模式, 但 0.90.x 需要禁用表。

            6.1.1. 模式更新

            當表或列族改變時(如 region size, block size), 當下次存在主緊縮及存儲文件重寫時起作用。

            參考 Section 9.7.5, “Store” 獲取存儲文件的更多信息。


            6.2.  列族的數量

            現在HBase并不能很好的處理兩個或者三個以上的列族,所以盡量讓你的列族數量少一些。目前,flush和compaction操作是針對一個Region。所以當一個列族操作大量數據的時候會引發一個flush。那些不相關的列族也有進行flush操作,盡管他們沒有操作多少數據。Compaction操作現在是根據一個列族下的全部文件的數量觸發的,而不是根據文件大小觸發的。當很多的列族在flush和compaction時,會造成很多沒用的I/O負載(要想解決這個問題,需要將flush和compaction操作只針對一個列族) 。 更多緊縮信息, 參考Section 9.7.5.5, “Compaction”.

            盡量在你的應用中使用一個列族。只有你的所有查詢操作只訪問一個列族的時候,可以引入第二個和第三個列族.例如,你有兩個列族,但你查詢的時候總是訪問其中的一個,從來不會兩個一起訪問。

            6.2.1. 列族的基數

            一個表存在多列族,注意基數(如, 行數). 如果列族A有100萬行,列族B有10億行,列族A可能被分散到很多很多區(及區服務器)。這導致掃描列族A低效。

             

            6.3.  行鍵(RowKey)設計

            6.3.1. 單調遞增行鍵/時序數據

            在Tom White的Hadoop: The Definitive Guide一書中,有一個章節描述了一個值得注意的問題:在一個集群中,一個導入數據的進程一動不動,所有的client都在等待一個region(就是一個節點),過了一會后,變成了下一個region...如果使用了單調遞增或者時序的key就會造成這樣的問題。詳情可以參見IKai畫的漫畫monotonically increasing values are bad。使用了順序的key會將本沒有順序的數據變得有順序,把負載壓在一臺機器上。所以要盡量避免時間戳或者(e.g. 1, 2, 3)這樣的key。

            如果你需要導入時間順序的文件(如log)到HBase中,可以學習OpenTSDB的做法。他有一個頁面來描述他的schema.OpenTSDB的Key的格式是[metric_type][event_timestamp],乍一看,似乎違背了不將timestamp做key的建議,但是他并沒有將timestamp作為key的一個關鍵位置,有成百上千的metric_type就足夠將壓力分散到各個region了。

            6.3.2. 盡量最小化行和列的大小(為何我的存儲文件指示很大?)

            在HBase中,值是作為一個單元(Cell)保存在系統的中的,要定位一個單元,需要行,列名和時間戳。通常情況下,如果你的行和列的名字要是太大(甚至比value的大小還要大)的話,你可能會遇到一些有趣的情況。例如Marc Limotte 在 HBASE-3551(推薦!)尾部提到的現象。在HBase的存儲文件Section 9.7.5.2, “StoreFile (HFile)”中,有一個索引用來方便值的隨機訪問,但是訪問一個單元的坐標要是太大的話,會占用很大的內存,這個索引會被用盡。所以要想解決,可以設置一個更大的塊大小,當然也可以使用更小的列名 。壓縮也能得到更大指數。參考話題 a question storefileIndexSize 用戶郵件列表.

            大部分時候,小的低效不會影響很大。不幸的是,這里會是個問題。無論是列族,屬性和行鍵都會在數據中重復上億次。參考 Section 9.7.5.4, “KeyValue” 獲取更多信息,關于HBase 內部保存數據,了解為什么這很重要。

            6.3.2.1. 列族

            盡量使列族名小,最好一個字符。(如 "d" 表示 data/default).

            參考 Section 9.7.5.4, “KeyValue” 獲取更多信息,關于HBase 內部保存數據,了解為什么這很重要。

            6.3.2.2. 屬性

            詳細屬性名 (如, "myVeryImportantAttribute") 易讀,最好還是用短屬性名 (e.g., "via") 保存到HBase.

            參考 Section 9.7.5.4, “KeyValue” 獲取更多信息,關于HBase 內部保存數據,了解為什么這很重要。

            6.3.2.3. 行鍵長度

            讓行鍵短到可讀即可,這樣對獲取數據有用(e.g., Get vs. Scan)。 短鍵對訪問數據無用,并不比長鍵對get/scan更好。設計行鍵需要權衡。

            6.3.2.4. 字節模式

            long 類型有 8 字節. 8字節內可以保存無符號數字到18,446,744,073,709,551,615. 如果用字符串保存--假設一個字節一個字符--,需要將近3倍的字節數。

            不信下面是示例代碼,可以自己運行一下。

            // long
            //
            long l = 1234567890L;
            byte[] lb = Bytes.toBytes(l);
            System.out.println("long bytes length: " + lb.length);   // returns 8
            		
            String s = "" + l;
            byte[] sb = Bytes.toBytes(s);
            System.out.println("long as string length: " + sb.length);    // returns 10
            			
            // hash 
            //
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(Bytes.toBytes(s));
            System.out.println("md5 digest bytes length: " + digest.length);    // returns 16
            		
            String sDigest = new String(digest);
            byte[] sbDigest = Bytes.toBytes(sDigest);
            System.out.println("md5 digest as string length: " + sbDigest.length);    // returns 26(譯者注:實測值為22)		
            

            6.3.3. 倒序時間戳

            一個數據庫處理的通常問題是找到最近版本的值。采用倒序時間戳作為鍵的一部分可以對此特定情況有很大幫助。也在Tom White的Hadoop書籍的HBase 章節能找到: The Definitive Guide (O'Reilly), 該技術包含追加(Long.MAX_VALUE - timestamp) 到key的后面,如 [key][reverse_timestamp].

            表內[key]的最近的值可以用[key]進行 Scan 找到并獲取第一個記錄。由于 HBase 行鍵是排序的,該鍵排在任何比它老的行鍵的前面,所以必然是第一個。

            該技術可以用于代替Section 6.4, “ 版本的數量 ” ,其目的是保存所有版本到“永遠”(或一段很長時間) 。同時,采用同樣的Scan技術,可以很快獲取其他版本。

            6.3.4. 行鍵和列族

            行鍵在列族范圍內。所以同樣的行鍵可以在同一個表的每個列族中存在而不會沖突。

            6.3.5. 行鍵永遠不變

            行鍵不能改變。唯一可以“改變”的方式是刪除然后再插入。這是一個網上常問問題,所以要注意開始就要讓行鍵正確(且/或在插入很多數據之前)。

            6.4.  版本數量

            6.4.1. 最大版本數

            行的版本的數量是HColumnDescriptor設置的,每個列族可以單獨設置,默認是3。這個設置是很重要的,在Chapter 5, 數據模型有描述,因為HBase是不會去覆蓋一個值的,他只會在后面在追加寫,用時間戳來區分、過早的版本會在執行主緊縮的時候刪除。這個版本的值可以根據具體的應用增加減少。

            不推薦將版本最大值設到一個很高的水平 (如, 成百或更多),除非老數據對你很重要。因為這會導致存儲文件變得極大。

            6.4.2.  最小版本數

            和行的最大版本數一樣,最小版本數也是通過HColumnDescriptor 在每個列族中設置的。最小版本數缺省值是0,表示該特性禁用。 最小版本數參數和存活時間一起使用,允許配置如“保存最后T秒有價值數據,最多N個版本,但最少約M個版本”(M是最小版本數,M<N)。 該參數僅在存活時間對列族啟用,且必須小于行版本數。

            6.5.  支持數據類型

            HBase 通過 Put 和 Result支持 "bytes-in/bytes-out" 接口,所以任何可被轉為字節數組的東西可以作為值存入。輸入可以是字符串,數字,復雜對象,甚至圖像,只要他們能轉為字節。

            存在值的實際長度限制 (如 保存 10-50MB 對象到 HBase 可能對查詢來說太長); 搜索郵件列表獲取本話題的對話。 HBase的所有行都遵循 Chapter 5, 數據模型, 包括版本化。 設計時需考慮到這些,以及列族的塊大小。

            6.5.1. 計數器

            一種支持的數據類型,值得一提的是“計數器”(如, 具有原子遞增能力的數值)。參考 HTable的 Increment .

            同步計數器在區域服務器中完成,不是客戶端。

            6.6. 聯合

            如果有多個表,不要在模式設計中忘了 Section 5.11, “Joins” 的潛在因素。

            6.7. 存活時間 (TTL)

            列族可以設置TTL秒數,HBase 在超時后將自動刪除數據。影響 全部 行的全部版本 - 甚至當前版本。HBase里面TTL 時間時區是 UTC.

            參考 HColumnDescriptor 獲取更多信息。

            6.8.  保留刪除的單元

            列族允許是否保留單元。這就是說  Get 或 Scan 操作仍可以獲取刪除的單元。由于這些操作指定時間范圍,結束在刪除單元發生效果之前。這甚至允許在刪除進行時進行即時查詢。

            刪除的單元仍然受TTL控制,并永遠不會超過“最大版本數”被刪除的單元。新 "raw" scan 選項返回所有已刪除的行和刪除標志。

            參考 HColumnDescriptor 獲取更多信息

            6.9.  第二索引和改變路徑查詢

            本節標題也可以為"如果表的行鍵像這樣 ,但我又想像那樣查詢該表." A common example on the dist-list is where a row-key is of the format "user-timestamp" but there are are reporting requirements on activity across users for certain time ranges. Thus, selecting by user is easy because it is in the lead position of the key, but time is not.

            There is no single answer on the best way to handle this because it depends on...

            • Number of users
            • Data size and data arrival rate
            • Flexibility of reporting requirements (e.g., completely ad-hoc date selection vs. pre-configured ranges)
            • Desired execution speed of query (e.g., 90 seconds may be reasonable to some for an ad-hoc report, whereas it may be too long for others)

            ... and solutions are also influenced by the size of the cluster and how much processing power you have to throw at the solution. Common techniques are in sub-sections below. This is a comprehensive, but not exhaustive, list of approaches.

            It should not be a surprise that secondary indexes require additional cluster space and processing. This is precisely what happens in an RDBMS because the act of creating an alternate index requires both space and processing cycles to update. RBDMS products are more advanced in this regard to handle alternative index management out of the box. However, HBase scales better at larger data volumes, so this is a feature trade-off.

            Pay attention to Chapter 11, Performance Tuning when implementing any of these approaches.

            Additionally, see the David Butler response in this dist-list thread HBase, mail # user - Stargate+hbase

            6.9.1.  過濾查詢

            根據具體應用,可能和 Section 9.4, “Client Request Filters” 用法相當。在這種情況下,沒有第二索引被創建。然而,不要像這樣從應用 (如單線程客戶端)中對大表嘗試全表掃描。

            6.9.2.  定期更新第二索引

            第二索引可以在另一個表中創建,并通過MapReduce任務定期更新。任務可以在當天執行,但依賴于加載策略,可能會同主表失去同步。

            參考 Section 7.2.2, “HBase MapReduce Read/Write Example” 獲取更多信息.

            6.9.3.  雙寫第二索引

            另一個策略是在將數據寫到集群的同時創建第二索引(如:寫到數據表,同時寫到索引表)。如果該方法在數據表存在之后采用,則需要利用MapReduce任務來生成已有數據的第二索引。 (參考 Section 6.9.2, “ Periodic-Update Secondary Index ”).

            6.9.4.  匯總表(Summary Tables)

            對時間跨度長 (e.g., 年報) 和數據量巨大,匯總表是通用路徑。可通過MapReduce任務生成到另一個表。

            參考 Section 7.2.4, “HBase MapReduce Summary to HBase Example” 獲取更多信息。

            6.9.5.  協處理第二索引

            協處理動作像 RDBMS 觸發器。 這在 0.92中添加. 更多參考 Section 9.6.3, “Coprocessors”

            6.10. 限制

            HBase currently supports 'constraints' in traditional (SQL) database parlance. The advised usage for Constraints is in enforcing business rules for attributes in the table (eg. make sure values are in the range 1-10). Constraints could also be used to enforce referential integrity, but this is strongly discouraged as it will dramatically decrease the write throughput of the tables where integrity checking is enabled. Extensive documentation on using Constraints can be found at: Constraint since version 0.94.

             

            6.11. 模式(schema)設計用例

            This effectively is the OpenTSDB approach. What OpenTSDB does is re-write data and pack rows into columns for certain time-periods. For a detailed explanation, see:http://opentsdb.net/schema.html, and Lessons Learned from OpenTSDB from HBaseCon2012.

            But this is how the general concept works: data is ingested, for example, in this manner…

            [hostname][log-event][timestamp1]  [hostname][log-event][timestamp2]  [hostname][log-event][timestamp3]  

            … with separate rowkeys for each detailed event, but is re-written like this…

            [hostname][log-event][timerange]

            … and each of the above events are converted into columns stored with a time-offset relative to the beginning timerange (e.g., every 5 minutes). This is obviously a very advanced processing technique, but HBase makes this possible.

            6.11.3. Case Study - Customer/Order

            Assume that HBase is used to store customer and order information. There are two core record-types being ingested: a Customer record type, and Order record type.

            The Customer record type would include all the things that you’d typically expect:

            • Customer number
            • Customer name
            • Address (e.g., city, state, zip)
            • Phone numbers, etc.

            The Order record type would include things like:

            Assuming that the combination of customer number and sales order uniquely identify an order, these two attributes will compose the rowkey, and specifically a composite key such as:

            [customer number][order number]

            … for a ORDER table. However, there are more design decisions to make: are the raw values the best choices for rowkeys?

            The same design questions in the Log Data use-case confront us here. What is the keyspace of the customer number, and what is the format (e.g., numericalphanumeric?) As it is advantageous to use fixed-length keys in HBase, as well as keys that can support a reasonable spread in the keyspace, similar options appear:

            Composite Rowkey With Hashes:

            • [MD5 of customer number] = 16 bytes
            • [MD5 of order number] = 16 bytes

            Composite Numeric/Hash Combo Rowkey:

            • [substituted long for customer number] = 8 bytes
            • [MD5 of order number] = 16 bytes

            6.11.3.1. Single TableMultiple Tables?

            A traditional design approach would have separate tables for CUSTOMER and SALES. Another option is to pack multiple record types into a single table (e.g., CUSTOMER++).

            Customer Record Type Rowkey:

            • [customer-id]
            • [type] = type indicating ‘1’ for customer record type

            Order Record Type Rowkey:

            • [customer-id]
            • [type] = type indicating ‘2’ for order record type
            • [order]

            The advantage of this particular CUSTOMER++ approach is that organizes many different record-types by customer-id (e.g., a single scan could get you everything about that customer). The disadvantage is that it’s not as easy to scan for a particular record-type.

            6.11.3.2. Order Object Design

            Now we need to address how to model the Order object. Assume that the class structure is as follows:

            Order       ShippingLocation     (an Order can have multiple ShippingLocations)            LineItem               (a ShippingLocation can have multiple LineItems)  

            ... there are multiple options on storing this data.

            6.11.3.2.1. Completely Normalized

            With this approach, there would be separate tables for ORDER, SHIPPING_LOCATION, and LINE_ITEM.

            The ORDER table's rowkey was described above: Section 6.11.3, “Case Study - Customer/Order”

            The SHIPPING_LOCATION's composite rowkey would be something like this:

            • [order-rowkey]
            • [shipping location number] (e.g., 1st location, 2nd, etc.)

            The LINE_ITEM table's composite rowkey would be something like this:

            • [order-rowkey]
            • [shipping location number] (e.g., 1st location, 2nd, etc.)
            • [line item number] (e.g., 1st lineitem, 2nd, etc.)

            Such a normalized model is likely to be the approach with an RDBMS, but that's not your only option with HBase. The cons of such an approach is that to retrieve information about any Order, you will need:

            • Get on the ORDER table for the Order
            • Scan on the SHIPPING_LOCATION table for that order to get the ShippingLocation instances
            • Scan on the LINE_ITEM for each ShippingLocation

            ... granted, this is what an RDBMS would do under the covers anyway, but since there are no joins in HBase you're just more aware of this fact.

            6.11.3.2.2. Single Table With Record Types

            With this approach, there would exist a single table ORDER that would contain

            The Order rowkey was described above: Section 6.11.3, “Case Study - Customer/Order”

            • [order-rowkey]
            • [ORDER record type]

            The ShippingLocation composite rowkey would be something like this:

            • [order-rowkey]
            • [SHIPPING record type]
            • [shipping location number] (e.g., 1st location, 2nd, etc.)

            The LineItem composite rowkey would be something like this:

            • [order-rowkey]
            • [LINE record type]
            • [shipping location number] (e.g., 1st location, 2nd, etc.)
            • [line item number] (e.g., 1st lineitem, 2nd, etc.)
            6.11.3.2.3. Denormalized

            A variant of the Single Table With Record Types approach is to denormalize and flatten some of the object hierarchy, such as collapsing the ShippingLocation attributes onto each LineItem instance.

            The LineItem composite rowkey would be something like this:

            • [order-rowkey]
            • [LINE record type]
            • [line item number] (e.g., 1st lineitem, 2nd, etc. - care must be taken that there are unique across the entire order)

            ... and the LineItem columns would be something like this:

            • itemNumber
            • quantity
            • price
            • shipToLine1 (denormalized from ShippingLocation)
            • shipToLine2 (denormalized from ShippingLocation)
            • shipToCity (denormalized from ShippingLocation)
            • shipToState (denormalized from ShippingLocation)
            • shipToZip (denormalized from ShippingLocation)

            The pros of this approach include a less complex object heirarchy, but one of the cons is that updating gets more complicated in case any of this information changes.

            6.11.3.2.4. Object BLOB

            With this approach, the entire Order object graph is treated, in one way or another, as a BLOB. For example, the ORDER table's rowkey was described above: Section 6.11.3, “Case Study - Customer/Order”, and a single column called "order" would contain an object that could be deserialized that contained a container Order, ShippingLocations, and LineItems.

            There are many options here: JSON, XML, Java Serialization, Avro, Hadoop Writables, etc. All of them are variants of the same approach: encode the object graph to a byte-array. Care should be taken with this approach to ensure backward compatibilty in case the object model changes such that older persisted structures can still be read back out of HBase.

            Pros are being able to manage complex object graphs with minimal I/O (e.g., a single HBase Get per Order in this example), but the cons include the aforementioned warning about backward compatiblity of serialization, language dependencies of serialization (e.g., Java Serialization only works with Java clients), the fact that you have to deserialize the entire object to get any piece of information inside the BLOB, and the difficulty in getting frameworks like Hive to work with custom objects like this.

            6.11.4. Case Study - "Tall/Wide/Middle" Schema Design Smackdown

            This section will describe additional schema design questions that appear on the dist-list, specifically about tall and wide tables. These are general guidelines and not laws - each application must consider its own needs.

            6.11.4.1. Rows vs. Versions

            A common question is whether one should prefer rows or HBase's built-in-versioning. The context is typically where there are "a lot" of versions of a row to be retained (e.g., where it is significantly above the HBase default of 3 max versions). The rows-approach would require storing a timstamp in some portion of the rowkey so that they would not overwite with each successive update.

            Preference: Rows (generally speaking).

            6.11.4.2. Rows vs. Columns

            Another common question is whether one should prefer rows or columns. The context is typically in extreme cases of wide tables, such as having 1 row with 1 million attributes, or 1 million rows with 1 columns apiece.

            Preference: Rows (generally speaking). To be clear, this guideline is in the context is in extremely wide cases, not in the standard use-case where one needs to store a few dozen or hundred columns. But there is also a middle path between these two options, and that is "Rows as Columns."

            6.11.4.3. Rows as Columns

            The middle path between Rows vs. Columns is packing data that would be a separate row into columns, for certain rows. OpenTSDB is the best example of this case where a single row represents a defined time-range, and then discrete events are treated as columns. This approach is often more complex, and may require the additional complexity of re-writing your data, but has the advantage of being I/O efficient. For an overview of this approach, see ???.

            6.11.5. Case Study - List Data

            The following is an exchange from the user dist-list regarding a fairly common question: how to handle per-user list data in Apache HBase.

            *** QUESTION ***

            We're looking at how to store a large amount of (per-user) list data in HBase, and we were trying to figure out what kind of access pattern made the most sense. One option is store the majority of the data in a key, so we could have something like:

            <FixedWidthUserName><FixedWidthValueId1>:"" (no value)  <FixedWidthUserName><FixedWidthValueId2>:"" (no value)  <FixedWidthUserName><FixedWidthValueId3>:"" (no value)  			
            The other option we had was to do this entirely using:
            <FixedWidthUserName><FixedWidthPageNum0>:<FixedWidthLength><FixedIdNextPageNum><ValueId1><ValueId2><ValueId3>...  <FixedWidthUserName><FixedWidthPageNum1>:<FixedWidthLength><FixedIdNextPageNum><ValueId1><ValueId2><ValueId3>...      		

            where each row would contain multiple values. So in one case reading the first thirty values would be:

            scan { STARTROW => 'FixedWidthUsername' LIMIT => 30}      		
            And in the second case it would be
            get 'FixedWidthUserName\x00\x00\x00\x00'      		

            The general usage pattern would be to read only the first 30 values of these lists, with infrequent access reading deeper into the lists. Some users would have <= 30 total values in these lists, and some users would have millions (i.e. power-law distribution)

            The single-value format seems like it would take up more space on HBase, but would offer some improved retrieval / pagination flexibility. Would there be any significant performance advantages to be able to paginate via gets vs paginating with scans?

            My initial understanding was that doing a scan should be faster if our paging size is unknown (and caching is set appropriately), but that gets should be faster if we'll always need the same page size. I've ended up hearing different people tell me opposite things about performance. I assume the page sizes would be relatively consistent, so for most use cases we could guarantee that we only wanted one page of data in the fixed-page-length case. I would also assume that we would have infrequent updates, but may have inserts into the middle of these lists (meaning we'd need to update all subsequent rows).

            Thanks for help / suggestions / follow-up questions.

            *** ANSWER ***

            If I understand you correctly, you're ultimately trying to store triples in the form "user, valueid, value", rightE.g., something like:

            "user123, firstname, Paul",  "user234, lastname, Smith"  			

            (But the usernames are fixed width, and the valueids are fixed width).

            And, your access pattern is along the lines of: "for user X, list the next 30 values, starting with valueid Y". Is that rightAnd these values should be returned sorted by valueid?

            The tl;dr version is that you should probably go with one row per user+value, and not build a complicated intra-row pagination scheme on your own unless you're really sure it is needed.

            Your two options mirror a common question people have when designing HBase schemas: should I go "tall" or "wide"Your first schema is "tall": each row represents one value for one user, and so there are many rows in the table for each user; the row key is user + valueid, and there would be (presumably) a single column qualifier that means "the value". This is great if you want to scan over rows in sorted order by row key (thus my question above, about whether these ids are sorted correctly). You can start a scan at any user+valueid, read the next 30, and be done. What you're giving up is the ability to have transactional guarantees around all the rows for one user, but it doesn't sound like you need that. Doing it this way is generally recommended (see here #schema.smackdown).

            Your second option is "wide": you store a bunch of values in one row, using different qualifiers (where the qualifier is the valueid). The simple way to do that would be to just store ALL values for one user in a single row. I'm guessing you jumped to the "paginated" version because you're assuming that storing millions of columns in a single row would be bad for performance, which may or may not be true; as long as you're not trying to do too much in a single request, or do things like scanning over and returning all of the cells in the row, it shouldn't be fundamentally worse. The client has methods that allow you to get specific slices of columns.

            Note that neither case fundamentally uses more disk space than the other; you're just "shifting" part of the identifying information for a value either to the left (into the row key, in option one) or to the right (into the column qualifiers in option 2). Under the covers, every key/value still stores the whole row key, and column family name. (If this is a bit confusing, take an hour and watch Lars George's excellent video about understanding HBase schema design: http://www.youtube.com/watch?v=_HLoH_PgrLk).

            A manually paginated version has lots more complexities, as you note, like having to keep track of how many things are in each page, re-shuffling if new values are inserted, etc. That seems significantly more complex. It might have some slight speed advantages (or disadvantages!) at extremely high throughput, and the only way to really know that would be to try it out. If you don't have time to build it both ways and compare, my advice would be to start with the simplest option (one row per user+value). Start simple and iterate! :)

             

            6.12. 業務和性能配置選項

            參考 the Performance section Section 11.6, “Schema Design” for more information operational and performance schema design options, such as Bloom Filters, Table-configured regionsizes, compression, and blocksizes.

             

             

            Chapter 7. HBase 和 MapReduce

            關于 HBase 和 MapReduce詳見 javadocs. 下面是一些附加的幫助文檔. MapReduce的更多信息 (如,通用框架), 參考 Hadoop MapReduce Tutorial.

            7.1. Map-Task 分割

            7.1.1 默認 HBase MapReduce 分割器(Splitter)

            當 MapReduce 任務的HBase 表使用TableInputFormat為數據源格式的時候,他的splitter會給這個table的每個region一個map。因此,如果一個table有100個region,就有100個map-tasks,不論需需要scan多少個列族 。

            7.1.2. 自定義分割器

            iv>

            For those interested in implementing custom splitters, see the method getSplits in TableInputFormatBase. That is where the logic for map-task assignment resides.

             

            7.2. HBase MapReduce 例子

            7.2.1 HBase MapReduce 讀取例子

            下面是使用HBase 作為源的MapReduce讀取示例。特別是僅有Mapper實例,沒有Reducer。Mapper什么也不產生。

            如下所示...

            Configuration config = HBaseConfiguration.create();
            Job job = new Job(config, "ExampleRead");
            job.setJarByClass(MyReadJob.class); // class that contains mapper

            Scan scan = new Scan();
            scan.setCaching(500); // 1 is the default in Scan, which will be bad for MapReduce jobs
            scan.setCacheBlocks(false); // don't set to true for MR jobs
            // set other scan attrs
            ...

            TableMapReduceUtil.initTableMapperJob(
            tableName, // input HBase table name
            scan, // Scan instance to control CF and attribute selection
            MyMapper.class, // mapper
            null, // mapper output key
            null, // mapper output value
            job);
            job.setOutputFormatClass(NullOutputFormat.class); // because we aren't emitting anything from mapper

            boolean b = job.waitForCompletion(true);
            if (!b) {
            throw new IOException("error with job!");
            }

            ...mapper需要繼承于TableMapper...

            public class MyMapper extends TableMapper<Text, LongWritable> {
            public void map(ImmutableBytesWritable row, Result value, Context context) 
            throws InterruptedException, IOException {
            // process data for the row from the Result instance.

            7.2.2. HBase MapReduce 讀/寫 示例

            下面是使用HBase 作為源和目標的MapReduce示例. 本示例簡單從一個表復制到另一個表。

            Configuration config = HBaseConfiguration.create();
            Job job = new Job(config,"ExampleReadWrite");
            job.setJarByClass(MyReadWriteJob.class);    // class that contains mapper
            	        	        
            Scan scan = new Scan();
            scan.setCaching(500);        // 1 is the default in Scan, which will be bad for MapReduce jobs
            scan.setCacheBlocks(false);  // don't set to true for MR jobs
            // set other scan attrs
            	        
            TableMapReduceUtil.initTableMapperJob(
            	sourceTable,      // input table
            	scan,	          // Scan instance to control CF and attribute selection
            	MyMapper.class,   // mapper class
            	null,	          // mapper output key
            	null,	          // mapper output value
            	job);
            TableMapReduceUtil.initTableReducerJob(
            	targetTable,      // output table
            	null,             // reducer class
            	job);
            job.setNumReduceTasks(0);
            	        
            boolean b = job.waitForCompletion(true);
            if (!b) {
                throw new IOException("error with job!");
            }
                

            TableMapReduceUtil做了什么需要解釋, 特別是對 reducer. TableOutputFormat 作為 outputFormat 類, 幾個參數在config中設置(e.g., TableOutputFormat.OUTPUT_TABLE), 同時設置reducer output key 到 ImmutableBytesWritable 和 reducer value到 Writable. 這可以編程時設置到job和conf,但TableMapReduceUtil 使其變簡單.

            下面是 mapper示例, 創建一個 Put,匹配輸入的 Result 并提交. Note: 這是 CopyTable 工具做的.

            public static class MyMapper extends TableMapper<ImmutableBytesWritable, Put>  {
            
            	public void map(ImmutableBytesWritable row, Result value, Context context) throws IOException, InterruptedException {
            		// this example is just copying the data from the source table...
               		context.write(row, resultToPut(row,value));
               	}
                    
              	private static Put resultToPut(ImmutableBytesWritable key, Result result) throws IOException {
              		Put put = new Put(key.get());
             		for (KeyValue kv : result.raw()) {
            			put.add(kv);
            		}
            		return put;
               	}
            }
                

            這不是真正的 reducer 步驟, 所以 TableOutputFormat 處理發送 Put 到目標表.

            這僅是示例, 開發者可以選擇不使用TableOutputFormat并自己連接到目標表。

            7.2.3. HBase MapReduce Read/Write 多表輸出示例

            TODO: MultiTableOutputFormat 示例.

            7.2.4. HBase MapReduce 匯總到 HBase 示例

            下面是使用HBase 作為源和目標的MapReduce示例,具有匯總步驟。本示例計算一個表中值的個數,并將匯總的計數輸出到另一個表。

            Configuration config = HBaseConfiguration.create();
            Job job = new Job(config,"ExampleSummary");
            job.setJarByClass(MySummaryJob.class);     // class that contains mapper and reducer
            	        
            Scan scan = new Scan();
            scan.setCaching(500);        // 1 is the default in Scan, which will be bad for MapReduce jobs
            scan.setCacheBlocks(false);  // don't set to true for MR jobs
            // set other scan attrs
            	        
            TableMapReduceUtil.initTableMapperJob(
            	sourceTable,        // input table
            	scan,               // Scan instance to control CF and attribute selection
            	MyMapper.class,     // mapper class
            	Text.class,         // mapper output key
            	IntWritable.class,  // mapper output value
            	job);
            TableMapReduceUtil.initTableReducerJob(
            	targetTable,        // output table
            	MyTableReducer.class,    // reducer class
            	job);
            job.setNumReduceTasks(1);   // at least one, adjust as required
            	    
            boolean b = job.waitForCompletion(true);
            if (!b) {
            	throw new IOException("error with job!");
            }    
                

            本示例mapper,將一個列的一個字符串值作為匯總值。該值作為key在mapper中生成。 IntWritable 代表一個實例計數。

            public static class MyMapper extends TableMapper<Text, IntWritable>  {
            
            	private final IntWritable ONE = new IntWritable(1);
               	private Text text = new Text();
                	
               	public void map(ImmutableBytesWritable row, Result value, Context context) throws IOException, InterruptedException {
                    	String val = new String(value.getValue(Bytes.toBytes("cf"), Bytes.toBytes("attr1")));
                      	text.set(val);     // we can only emit Writables...
            
                    	context.write(text, ONE);
               	}
            }
                

            在 reducer, "ones" 被統計 (和其他 MR 示例一樣), 產生一個 Put.

            public static class MyTableReducer extends TableReducer<Text, IntWritable, ImmutableBytesWritable>  {
                    
             	public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
                		int i = 0;
                		for (IntWritable val : values) {
                			i += val.get();
                		}
                		Put put = new Put(Bytes.toBytes(key.toString()));
                		put.add(Bytes.toBytes("cf"), Bytes.toBytes("count"), Bytes.toBytes(i));
            
                		context.write(null, put);
               	}
            }
                

            7.2.5. HBase MapReduce 匯總到文件示例

            This very similar to the summary example above, with exception that this is using HBase as a MapReduce source but HDFS as the sink. The differences are in the job setup and in the reducer. The mapper remains the same.

            Configuration config = HBaseConfiguration.create();
            Job job = new Job(config,"ExampleSummaryToFile");
            job.setJarByClass(MySummaryFileJob.class);     // class that contains mapper and reducer
            	        
            Scan scan = new Scan();
            scan.setCaching(500);        // 1 is the default in Scan, which will be bad for MapReduce jobs
            scan.setCacheBlocks(false);  // don't set to true for MR jobs
            // set other scan attrs
            	        
            TableMapReduceUtil.initTableMapperJob(
            	sourceTable,        // input table
            	scan,               // Scan instance to control CF and attribute selection
            	MyMapper.class,     // mapper class
            	Text.class,         // mapper output key
            	IntWritable.class,  // mapper output value
            	job);
            job.setReducerClass(MyReducer.class);    // reducer class
            job.setNumReduceTasks(1);    // at least one, adjust as required
            FileOutputFormat.setOutputPath(job, new Path("/tmp/mr/mySummaryFile"));  // adjust directories as required
            	    
            boolean b = job.waitForCompletion(true);
            if (!b) {
            	throw new IOException("error with job!");
            }    
                
            As stated above, the previous Mapper can run unchanged with this example. As for the Reducer, it is a "generic" Reducer instead of extending TableMapper and emitting Puts.
             public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable>  {
                    
            	public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            		int i = 0;
            		for (IntWritable val : values) {
            			i += val.get();
            		}	
            		context.write(key, new IntWritable(i));
            	}
            }
                

            7.2.6. HBase MapReduce 沒有Reducer時匯總到 HBase

            It is also possible to perform summaries without a reducer - if you use HBase as the reducer.

            An HBase target table would need to exist for the job summary. The HTable method incrementColumnValue would be used to atomically increment values. From a performance perspective, it might make sense to keep a Map of values with their values to be incremeneted for each map-task, and make one update per key at during the cleanup method of the mapper. However, your milage may vary depending on the number of rows to be processed and unique keys.

            In the end, the summary results are in HBase.

            7.2.7. HBase MapReduce 匯總到 RDBMS

            有時更合適產生匯總到 RDBMS.這種情況下,可以將匯總直接通過一個自定義的reducer輸出到 RDBMS 。 setup 方法可以連接到 RDBMS (連接信息可以通過context的自定義參數傳遞), cleanup 可以關閉連接.

            關鍵需要理解job的多個reducer會影響匯總實現,必須在reducer中進行設計。無論是一個recucer還是多個reducer。不管對錯, 依賴于你的用例。認識到多個reducer分配到job,需要創建多個并發的RDBMS連接-可以擴充,但僅在一個點。

             public static class MyRdbmsReducer extends Reducer<Text, IntWritable, Text, IntWritable>  {
            
            	private Connection c = null;
            	
            	public void setup(Context context) {
              		// create DB connection...
              	}
                    
            	public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            		// do summarization
            		// in this example the keys are Text, but this is just an example
            	}
            	
            	public void cleanup(Context context) {
              		// close db connection
              	}
            	
            }
                

            最后,匯總的結果被寫入到 RDBMS 表.

            7.3. 在一個MapReduce Job中訪問其他的HBase Tables

            盡管現有的框架允許一個HBase table作為一個MapReduce job的輸入,其他的HBase table可以同時作為普通的表被訪問。例如在一個MapReduce的job中,可以在Mapper的setup方法中創建HTable實例。

            public class MyMapper extends TableMapper<Text, LongWritable> {
              private HTable myOtherTable;
            
              @Override
              public void setup(Context context) {
                myOtherTable = new HTable("myOtherTable");
              }

            7.4. 預測執行

            通常建議關掉針對HBase的MapReduce job的預測執行(speculative execution)功能。這個功能也可以用每個Job的配置來完成。對于整個集群,使用預測執行意味著雙倍的運算量。這可不是你所希望的。

            參考 Section 2.8.2.9, “Speculative Execution” 獲取更多信息。

            Chapter 8.  HBase安全

            8.1. 安全客戶端訪問HBase

            新版 HBase (>= 0.92) 支持客戶端可選 SASL 認證.

            這里描述如何設置HBase 和 HBase 客戶端,以安全連接到HBase 資源.

            8.1.1. 先決條件

            HBase 必須使用 安全Hadoop/HBase的新 maven 配置文件: -P security. Secure Hadoop dependent classes are separated under a pseudo-module in the security/ directory and are only included if built with the secure Hadoop profile.

            You need to have a working Kerberos KDC.

            A HBase configured for secure client access is expected to be running on top of a secured HDFS cluster. HBase must be able to authenticate to HDFS services. HBase needs Kerberos credentials to interact with the Kerberos-enabled HDFS daemons. Authenticating a service should be done using a keytab file. The procedure for creating keytabs for HBase service is the same as for creating keytabs for Hadoop. Those steps are omitted here. Copy the resulting keytab files to wherever HBase Master and RegionServer processes are deployed and make them readable only to the user account under which the HBase daemons will run.

            A Kerberos principal has three parts, with the form username/fully.qualified.domain.name@YOUR-REALM.COM. We recommend using hbase as the username portion.

            The following is an example of the configuration properties for Kerberos operation that must be added to the hbase-site.xml file on every server machine in the cluster. Required for even the most basic interactions with a secure Hadoop configuration, independent of HBase security.

                  <property>
                    <name>hbase.regionserver.kerberos.principal</name>
                    <value>hbase/_HOST@YOUR-REALM.COM</value>
                  </property>
                  <property>
                    <name>hbase.regionserver.keytab.file</name>
                    <value>/etc/hbase/conf/keytab.krb5</value>
                  </property>
                  <property>
                    <name>hbase.master.kerberos.principal</name>
                    <value>hbase/_HOST@YOUR-REALM.COM</value>
                  </property>
                  <property>
                    <name>hbase.master.keytab.file</name>
                    <value>/etc/hbase/conf/keytab.krb5</value>
                  </property>
                

            Each HBase client user should also be given a Kerberos principal. This principal should have a password assigned to it (as opposed to a keytab file). The client principal's maxrenewlife should be set so that it can be renewed enough times for the HBase client process to complete. For example, if a user runs a long-running HBase client process that takes at most 3 days, we might create this user's principal within kadmin with: addprinc -maxrenewlife 3days

            Long running daemons with indefinite lifetimes that require client access to HBase can instead be configured to log in from a keytab. For each host running such daemons, create a keytab with kadmin or kadmin.local. The procedure for creating keytabs for HBase service is the same as for creating keytabs for Hadoop. Those steps are omitted here. Copy the resulting keytab files to where the client daemon will execute and make them readable only to the user account under which the daemon will run.

            8.1.2. 安全操作的服務器端配置

            增加下列內容到 hbase-site.xml file on every server machine in the cluster:

                  <property>
                    <name>hbase.security.authentication</name>
                    <value>kerberos</value> 
                  </property> 
                  <property>
                    <name>hbase.security.authorization</name>
                    <value>true</value>
                  </property>
                  <property>
                    <name>hbase.rpc.engine</name>
                    <value>org.apache.hadoop.hbase.ipc.SecureRpcEngine</value>
                  </property>
                  <property>
                  <name>hbase.coprocessor.region.classes</name>
                    <value>org.apache.hadoop.hbase.security.token.TokenProvider</value>
                  </property>
                

            A full shutdown and restart of HBase service is required when deploying these configuration changes.

            8.1.3. 客戶端安全操作配置

            每個客戶端增加下列內容到 hbase-site.xml:

                  <property>
                    <name>hbase.security.authentication</name>
                    <value>kerberos</value>
                  </property> 
                  <property>
                    <name>hbase.rpc.engine</name>
                    <value>org.apache.hadoop.hbase.ipc.SecureRpcEngine</value>
                  </property>
                

            The client environment must be logged in to Kerberos from KDC or keytab via the kinit command before communication with the HBase cluster will be possible.

            Be advised that if the hbase.security.authentication and hbase.rpc.engine properties in the client- and server-side site files do not match, the client will not be able to communicate with the cluster.

            Once HBase is configured for secure RPC it is possible to optionally configure encrypted communication. To do so, 增加下列內容到 hbase-site.xml file on every client:

                  <property>
                    <name>hbase.rpc.protection</name>
                    <value>privacy</value>
                  </property>
                

            This configuration property can also be set on a per connection basis. Set it in the Configuration supplied to HTable:

                  Configuration conf = HBaseConfiguration.create();
                  conf.set("hbase.rpc.protection", "privacy");
                  HTable table = new HTable(conf, tablename);
                

            Expect a ~10% performance penalty for encrypted communication.

            8.1.4. 客戶端安全操作配置 - Thrift 網關

            每個Thrift網關增加下列內容到 hbase-site.xml:

                <property>
                  <name>hbase.thrift.keytab.file</name>
                  <value>/etc/hbase/conf/hbase.keytab</value>
                </property>
                <property>
                  <name>hbase.thrift.kerberos.principal</name>
                  <value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
                </property>
                

            Substitute the appropriate credential and keytab for $USER and $KEYTAB respectively.

            The Thrift gateway will authenticate with HBase using the supplied credential. No authentication will be performed by the Thrift gateway itself. All client access via the Thrift gateway will use the Thrift gateway's credential and have its privilege.

            8.1.5. 客戶端安全操作配置 - REST 網關

            每個REST網關增加下列內容到 hbase-site.xml:

                <property>
                  <name>hbase.rest.keytab.file</name>
                  <value>$KEYTAB</value>
                </property>
                <property>
                  <name>hbase.rest.kerberos.principal</name>
                  <value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
                </property>
                

            Substitute the appropriate credential and keytab for $USER and $KEYTAB respectively.

            The REST gateway will authenticate with HBase using the supplied credential. No authentication will be performed by the REST gateway itself. All client access via the REST gateway will use the REST gateway's credential and have its privilege.

            It should be possible