HBase環境搭建隨記
====軟件版本====
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環境搭建隨記