1. 程式人生 > >HBase環境搭建隨記

HBase環境搭建隨記

很多 數值 配置環境變量 釋放 響應時間 ack 臨時文件 leader eba

====軟件版本====

jdk:jdk-8u77-linux-x64.tar.gz

zookeeper:zookeeper-3.4.6.tar.gz

hadoop:hadoop-2.7.4.tar.gz

hbase:hbase-1.3.1-bin.tar.gz

====前提準備====

3臺vmware虛擬機(已配置無秘鑰訪問)

其中,/etc/hosts文件內容如下:

技術分享

====安裝jdk====

上傳安裝包,解壓縮,然後配置環境變量即可。

技術分享

正常配置之後,在服務器任意路徑執行java -version可以顯示java版本。如下所示。

技術分享

====安裝zookeeper====

這裏也不在過多描述,簡單羅列一下配置文件。

配置文件:zoo.cfg

技術分享

需要分別在3個節點的,dataDir路徑下生成節點的myid。

啟動並驗證zookeeper是否正常

啟動命令:/home/hadmin/zookeeper-3.4.6/bin/zkServer.sh start

查看狀態:/home/hadmin/zookeeper-3.4.6/bin/zkServer.sh status

啟動之後,3個節點的狀態分別如下:

技術分享

技術分享

技術分享

====安裝hadoop====

因為HBase的底層是基於Hadoop的hdfs的,所以在安裝HBase之前,必須要安裝Hadoop,並確保hdfs正常。

Hadoop的配置重點是各個配置文件,這裏只羅列各個配置文件的基礎信息(經驗證,這些基本上是必須要配置的),

需要配置環境變量的同時,共需要修改如下文件:

  • hadoop-env.sh(各節點相同)
  • core-site.xml(各節點相同)
  • hdfs-site.xml(各節點相同)
  • mapred-site.xml(各節點相同)
  • yarn-site.xml(各節點相同)
  • masters(各節點相同)
  • slaves(各節點相同)

配置文件路徑:/home/hadmin/hadoop-2.7.4/etc/hadoop

技術分享

1、環境變量

技術分享

2、hadoop-env.sh

修改JAVA_HOME即可。

技術分享

3、core-site.xml

<configuration>

<property>
<name>fs.defaultFS</name>
<value>hdfs://ns</value>
</property>

<property>
<name>hadoop.tmp.dir
</name> <value>/home/hadmin/data/hadoop/tmp</value> </property> <property> <name>dfs.journalnode.edits.dir</name> <value>/home/hadmin/data/hadoop/journal</value> </property> <property> <name>ha.zookeeper.quorum</name> <value>dscn1:2181,dscn2:2181,dscn3:2181</value> </property> </configuration>

4、hdfs-site.xml

<configuration>

<property>
<name>dfs.replication</name>
<value>2</value>
</property>

<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadmin/data/hadoop/hdfs/name</value>
</property>

<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadmin/data/hadoop/hdfs/data</value>
</property>

<property>
<name>dfs.permissions</name>
<value>false</value>
</property>

<property>
<name>dfs.nameservices</name>
<value>ns</value>
</property>

<property>
<name>dfs.ha.namenodes.ns</name>
<value>nn1,nn2</value>
</property>

<property>
<name>dfs.namenode.rpc-address.ns.nn1</name>
<value>dscn1:9000</value>
</property>

<property>
<name>dfs.namenode.rpc-address.ns.nn2</name>
<value>dscn2:9000</value>
</property>

<property>
<name>dfs.namenode.http-address.ns.nn1</name>
<value>dscn1:50070</value>
</property>

<property>
<name>dfs.namenode.http-address.ns.nn2</name>
<value>dscn2:50070</value>
</property>

<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://dscn1:8485;dscn2:8485;dscn3:8485/ns</value>
</property>

<property>
<name>dfs.ha.automatic-failover.enabled.ns</name>
<value>true</value>
</property>

<property>
<name>dfs.client.failover.proxy.provider.ns</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

<property>
<name>dfs.ha.fencing.methods</name>
<value>shell(/home/hadmin/dscs/bin/hdfs-fencing.sh)</value>
</property>

</configuration>

5、mapred-site.xml

<configuration>

<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

<property>
<name>mapreduce.reduce.memory.mb</name>
<value>128</value>
</property>

<property>
<name>mapreduce.map.memory.mb</name>
<value>256</value>
</property>

</configuration>

6、yarn-site.xml

<configuration>

<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>

<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>

<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>ns</value>
</property>

<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>

<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>dscn1</value>
</property>

<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>dscn2</value>
</property>

<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>dscn1:8088</value>
</property>

<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>dscn2:8088</value>
</property>

<property>
<name>yarn.resourcemanager.zk-address</name>
<value>dscn1:2181,dscn2:2181,dscn3:2181</value>
</property>

<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>

<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>

<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>1024</value>
</property>

<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>256</value>
</property>

<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>1024</value>
</property>

</configuration>

7、masters

dscn1
dscn2

8、slaves

dscn1
dscn2
dscn3

上述幾個文件配置完畢之後,按照如下順序啟動

■首次啟動:

1、在dscn1上

hdfs zkfc -formatZK

2、在3節點分別啟動:

hadoop-daemon.sh start journalnode

3、在dscn1上:

hdfs namenode -format

hadoop-daemon.sh start namenode

4、在dscn2上:

hdfs namenode -bootstrapStandby

hadoop-daemon.sh start namenode

5、在dscn1和dscn2上:

hadoop-daemon.sh start zkfc

6、在3個節點分別啟動:

hadoop-daemon.sh start datanode

7、在dscn1上:

start-yarn.sh

■以後每次啟動:

1、在dscn1上:

start-all.sh

2、在dscn1和dscn2上:

hadoop-daemon.sh start zkfc

■停止集群:

stop-all.sh

安裝是否正常,可以通過如下方式驗證:

1、通過hadoop命令來操作hdfs

瀏覽hdfs根目錄:hadoop fs -ls /

創建文件夾:hadoop fs -mkdir /test

技術分享

2、通過瀏覽器可以查看Hadoop集群狀態

其中,兩個namenode,需要有一個保持active狀態

技術分享

技術分享

3、通過瀏覽器可以查看hadoop applications狀態

技術分享

4、3個節點的jps進程如下:

dscn1:

技術分享

dscn2:

技術分享

dscn3:

技術分享

====安裝HBase====

hbase的安裝相對簡單,主要完成以下文件的配置:

1、hbase-env.sh

export HBASE_MANAGES_ZK=false
export HBASE_CLASSPATH=/home/hadmin/hadoop-2.7.4/etc/hadoop

其中,第二個配置一定要註意,這個配置的目的是讓HBase能夠找到hadoop的配置文件,從而與hdfs建立練習,如果不配置這個,會出現如下錯誤:

技術分享

另外,官方文檔上也提到了這點,並提供了2種解決方法,我這裏采用的是"方法a"。

技術分享

2、hbase-site.xml

<configuration>

<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<property>
<name>hbase.tmp.dir</name>
<value>/home/hadmin/data/hbase/tmp</value>
</property>

<property>
<name>hbase.zookeeper.quorum</name>
<value>dscn1,dscn2,dscn3</value>
</property>

<property>
<name>hbase.rootdir</name>
<value>hdfs://ns/hbase</value>
</property>

<property>
<name>hbase.master.port</name>
<value>60000</value>
</property>

<property>
<name>hbase.master.info.port</name>
<value>60010</value>
</property>

<property>
<name>hbase.regionserver.port</name>
<value>60020</value>
</property>

<property>
<name>hbase.regionserver.info.port</name>
<value>60030</value>
</property>

<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadmin/data/zk/data</value>
</property>

</configuration>

按照上述的配置文件完成配置之後,就可以啟動HBase了

啟動命令:/home/hadmin/hbase-1.3.1/bin/start-hbase.sh

停止命令:/home/hadmin/hbase-1.3.1/bin/stop-hbase.sh

啟動之後,可以通過如下幾個方面來驗證HBase集群是否正常。

1、查看jps進程

dscn1:

技術分享

dscn2:

技術分享

dscn3:

技術分享

2、通過HBase shell控制臺,創建表:

如下圖所示:

建表命令:create ‘t1‘, {NAME => ‘f1‘, VERSION => 2}

技術分享

3、通過程序連接HBase,創建表:

如下程序中,建立了一張MY_TABLE_TEST1的表,並且進行了預分區。

建表程序如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.io.compress.Compression;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.util.Bytes;

public class SplitRegion {
    private static final String TABLE_NAME = "MY_TABLE_TEST1";
    private static final String COLUMN_FAMILY = "df";

    public static void main(String[] args) throws Exception {
        System.out.print("[------]SplitRegion Start.\n");
        Configuration configuration= HBaseConfiguration.create();
        System.out.print("[------]step 1 succeed.\n");
        configuration.set("hbase.zookeeper.quorum", "192.168.6.3,192.168.6.4,192.168.6.5");
        HBaseAdmin admin = new HBaseAdmin(configuration);
        System.out.print("[------]step 2 succeed.\n");

        String table_name = TABLE_NAME;
        if (admin.tableExists(table_name)) {
            admin.disableTable(table_name);
            System.out.println("[----]disableTable table[" + table_name + "]\n");
            admin.deleteTable(table_name);
            System.out.println("[----]deleteTable table[" + table_name + "]\n");
        }

        HTableDescriptor desc = new HTableDescriptor(table_name);
        HColumnDescriptor family = new HColumnDescriptor(COLUMN_FAMILY.getBytes());
        //過期時間
        family.setTimeToLive(3 * 60 * 60 * 24);
        //按行過濾
        family.setBloomFilterType(BloomType.ROW);
        desc.addFamily(family);
        System.out.print("[------]step 3 succeed.\n");

        byte[][] splitKeys = {
                Bytes.toBytes("0"),
                Bytes.toBytes("2"),
                Bytes.toBytes("4"),
                Bytes.toBytes("6"),
                Bytes.toBytes("8"),
        };

        admin.createTable(desc, splitKeys);
        System.out.println("[----]createTable table[" + table_name + "]\n");
        System.out.print("[------]SplitRegion end.\n");
    }
}

工程pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <artifactId>hbase_sample</artifactId>
    <groupId>hbase_sample</groupId>
    <version>1.0</version>
    <modelVersion>4.0.0</modelVersion>
    <dependencies>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-common</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <outputDirectory>target/classes</outputDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

通過maven,將程序編譯完成,上傳jar包只服務器,運行程序結果如下:

技術分享

4、通過瀏覽器訪問HBase管理界面:

地址:http://192.168.6.3:60010/

從圖中可以看到,有3個Region Server,並有通過命令創建的【t1】表,以及通過程序創建的【MY_TABLE_TEST1】表。

技術分享

====HBase調優參數====

<configuration>

<!--
RegionServer的共享目錄,用來持久化HBase。
默認情況下HBase是寫到/tmp的。不改這個配置,數據會在重啟的時候丟失。
-->
<property>
<name>hbase.rootdir</name>
<value>hdfs://ns/hbase</value>
</property>

<!--
HBase的運行模式。false是單機模式,true是分布式模式。
若為false, HBase和Zookeeper會運行在同一個JVM裏面。
默認: false
-->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<!--
Zookeeper集群的地址列表,用逗號分割。
如果在hbase-env.sh設置了HBASE_MANAGES_ZK,這些ZooKeeper節點就會和HBase一起啟動。
默認: localhost。


部署的zookeeper越多,可靠性就越高,但是部署只能部署奇數個,主要為了便於選出leader。最好給每個zookeeper 1G的內存和獨立的磁盤,可以確保高性能。hbase.zookeeper.property.dataDir可以修改zookeeper保存數據的路徑。
-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>dscn11,dscn12,dscn13</value>
</property>

<!--
本地文件系統的臨時文件夾。
可以修改到一個更為持久的目錄上。(/tmp會在重啟時清除)
默認:${Java.io.tmpdir}/hbase-${user.name}
-->
<property>
<name>hbase.tmp.dir</name>
<value>/home/hadmin/data/hadoop</value>
</property>

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

小region對split和compaction友好,因為拆分region或compact小region裏的storefile速度很快,內存占用低。
缺點是split和compaction會很頻繁。
特別是數量較多的小region不停地split, compaction,會導致集群響應時間波動很大,region數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase的bug。
一般512以下的都算小region。

大region,則不太適合經常split和compaction,因為做一次compact和split會產生較長時間的停頓,對應用的讀寫性能沖擊非常大。
此外,大region意味著較大的storefile,compaction時對內存也是一個挑戰。
當然,大region也有其用武之地。如果你的應用場景中,某個時間點的訪問量較低,
那麽在此時做compact和split,既能順利完成split和compaction,又能保證絕大多數時間平穩的讀寫性能。

既然split和compaction如此影響性能,有沒有辦法去掉?
compaction是無法避免的,split倒是可以從自動調整為手動。
只要通過將這個參數值調大到某個很難達到的值,比如100G,就可以間接禁用自動split(RegionServer不會對未到達100G的region做split)。
再配合RegionSplitter這個工具,在需要split時,手動split。
手動split在靈活性和穩定性上比起自動split要高很多,相反,管理成本增加不多,比較推薦online實時系統使用。

內存方面,小region在設置memstore的大小值上比較靈活,大region則過大過小都不行,過大會導致flush時app的IO wait增高,過小則因store file過多影響讀性能。
-->
<property>
<name>hbase.hregion.max.filesize</name>
<value>1073741824</value>
</property>

<!--
RegionServers受理的RPC Server實例數量。
對於Master來說,這個屬性是Master受理的handler數量
默認: 10

RegionServer的請求處理IO線程數。
這個參數的調優與內存息息相關。
較少的IO線程,適用於處理單次請求內存消耗較高的Big PUT場景(大容量單次PUT或設置了較大cache的scan,均屬於Big PUT)或ReigonServer的內存比較緊張的場景。
較多的IO線程,適用於單次請求內存消耗低,TPS要求非常高的場景。設置該值的時候,以監控內存為主要參考。
這裏需要註意的是如果server的region數量很少,大量的請求都落在一個region上,因快速充滿memstore觸發flush導致的讀寫鎖會影響全局TPS,不是IO線程數越高越好。

-->
<property>
<name>hbase.regionserver.handler.count</name>
<value>600</value>
</property>

<!--
如果memstore有hbase.hregion.memstore.block.multiplier倍數的hbase.hregion.flush.size的大小,就會阻塞update操作。
這是為了預防在update高峰期會導致的失控。如果不設上界,flush的時候會花很長的時間來合並或者分割,最壞的情況就是引發out of memory異常。
默認: 2

當一個region裏的memstore占用內存大小超過hbase.hregion.memstore.flush.size兩倍的大小時,block該region的所有請求,進行flush,釋放內存。
雖然我們設置了region所占用的memstores總內存大小,比如64M,但想象一下,在最後63.9M的時候,我Put了一個200M的數據,
此時memstore的大小會瞬間暴漲到超過預期的hbase.hregion.memstore.flush.size的幾倍。

這個參數的作用是當memstore的大小增至超過hbase.hregion.memstore.flush.size 2倍時,block所有請求,遏制風險進一步擴大。
調優: 這個參數的默認值還是比較靠譜的。如果你預估你的正常應用場景(不包括異常)不會出現突發寫或寫的量可控,那麽保持默認值即可。
如果正常情況下,你的寫請求量就會經常暴長到正常的幾倍,那麽你應該調大這個倍數並調整其他參數值,
比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以預留更多內存,防止HBase server OOM。
-->
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>8</value>
</property>

<!--
當memstore的大小超過這個值的時候,會flush到磁盤。
這個值被一個線程每隔hbase.server.thread.wakefrequency檢查一下。
默認:134217728(128M)
-->
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>33554432</value>
</property>

<!--
默認值:0.4
這個參數的作用是防止內存占用過大,當ReigonServer內所有region的memstores所占用內存總和達到heap的40%時,
HBase會強制block所有的更新並flush這些region以釋放所有memstore占用的內存。

調優:這是一個Heap內存保護參數,默認值已經能適用大多數場景。
參數調整會影響讀寫,如果寫的壓力大導致經常超過這個閥值,則調小讀緩存hfile.block.cache.size增大該閥值,或者Heap余量較多時,不修改讀緩存大小。
如果在高壓情況下,也沒超過這個閥值,那麽建議你適當調小這個閥值再做壓測,確保觸發次數不要太多,然後還有較多Heap余量的時候,調大hfile.block.cache.size提高讀性能。
還有一種可能性是?hbase.hregion.memstore.flush.size保持不變,但RS維護了過多的region,要知道 region數量直接影響占用內存的大小。
-->
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.5</value>
</property>

<!--
BucketCache工作模式。heap、offheap和file
默認:none

這三種工作模式在內存邏輯組織形式以及緩存流程上都是相同的,參見上節講解。不同的是三者對應的最終存儲介質有所不同。
其中heap模式和offheap模式都使用內存作為最終存儲介質,
heap模式分配內存會從JVM提供的heap區分配,而後者會直接從操作系統分配。這兩種內存分配模式會對HBase實際工作性能產生一定的影響。
影響最大的無疑是GC ,相比heap模式,offheap模式因為內存屬於操作系統,所以基本不會產生CMS GC,也就在任何情況下都不會因為內存碎片導致觸發Full GC。

除此之外,在內存分配以及讀取方面,兩者性能也有不同,
比如,內存分配時heap模式需要首先從操作系統分配內存再拷貝到JVMheap,相比offheap直接從操作系統分配內存更耗時;
但是反過來,讀取緩存時heap模式可以從JVM heap中直接讀取,而offheap模式則需要首先從操作系統拷貝到JVM heap再讀取,顯得後者更費時。

file模式和前面兩者不同,它使用Fussion-IO或者SSD等作為存儲介質,相比昂貴的內存,這樣可以提供更大的存儲容量,因此可以極大地提升緩存命中率。
-->
<property>
<name>hbase.bucketcache.ioengine</name>
<value>offheap</value>
</property>

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

storefile的讀緩存占用Heap的大小百分比,0.2表示20%。該值直接影響數據讀的性能。
當然是越大越好,如果寫比讀少很多,開到0.4-0.5也沒問題。
如果讀寫較均衡,0.3左右。如果寫比讀多,果斷默認吧。
設置這個值的時候,你同時要參考?hbase.regionserver.global.memstore.upperLimit?,
該值是memstore占heap的最大百分比,兩個參數一個影響讀,一個影響寫。如果兩值加起來超過80-90%,會有OOM的風險,謹慎設置。
-->
<property>
<name>hfile.block.cache.size</name>
<value>0.3</value>
</property>

<!--
bucketcache的大小,小於1時為整體內存的比例,大於等於1時為cache的實際容量,單位M。默認0 
-->
<property>
<name>hbase.bucketcache.size</name>
<value>25600</value>
</property>

<!--
hdfs的副本數
默認:3
-->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>

<!--
是否使用HBase Replication(集群復制)功能
默認:false
HBase默認此特性是關閉的,需要在集群上(所有集群)進行設定並重啟集群,
-->
<property>
<name>hbase.replication</name>
<value>true</value>
</property>

<!--
-->
<property>
<name>replication.source.maxretriesmultiplier</name>
<value>300</value>
</property>

<!--
-->
<property>
<name>replication.source.sleepforretries</name>
<value>1</value> 
</property>

<!--
-->
<property>
<name>replication.sleep.before.failover</name>
<value>30000</value>
</property>

</configuration>

====HBase集群操作命令(待更新)====

====HBase集群備份及恢復(待更新)====

====HBase集群復制(待更新)====

====HBase快照(待更新)====

--END--

HBase環境搭建隨記