More Related Content Similar to Hbase运维碎碎念 (20) Hbase运维碎碎念5. Hbase运维碎碎念 JVM Heap 图片出处:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html 6. Hbase运维碎碎念 JVM Heap 简单来说,Heap分为年轻代(Young)/年老代(Old/ Tenured)/持久代(Perm) -Xms: Heap初始尺寸 -Xmx: Heap最大尺寸 -Xmn: 年轻代尺寸 -XX:NewRatio: 设置Young与Old的大小比例,-server时默认为1:2 -XX:SurvivorRatio: 设置Eden与Survivor的比例,默认为32。 -XX:MaxPermSize: 持久代大小,默认64M。 -XX:NewSize: 年轻代大小 -XX:MaxNewSize: 年轻代最大尺寸 -Xss: 每个线程的stack尺寸 -XX:MinHeapFreeRatio:空余堆内存小于40%时,JVM就会增大堆。 -XX:MaxHeapFreeRatio:空余堆内存大于70%时,JVM会减少堆。 7. Hbase运维碎碎念 JVM Heap 年轻代分为Eden,Survior 1, Survior2 新对象在Eden区分配内存。 GC时,将Eden和有对象的Survior区(From Space)的所有对象复制到另外一个Survior(To Space),然后清空Eden和原Sruvior。 当一个对象在from和to之间复制的次数超过一定阀值(-XX:MaxTenuringThreshold)后,进入到年老代。如果是CMS GC,这个阀值默认为0,也就是经过一次copy后就进入年老代。 -XX:+PrintTenuringDistribution可以查看详细统计信息。 持久代不GC,除非CMS GC且显式设置 XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 8. Hbase运维碎碎念 JVM GC GC分为对Young的GC(minor)和同时对Young和Old的GC(Major) Serial GC,单线程GC,适合小Heap单CPU。-XX:+UseSerialGC Parallel GC,也称Throughput GC。与第一种GC不同在于Young区是多线程的,但Old区仍然单线程。-XX:+UseParallelGC。Java 6.0已经支持Old区并行GC: -XX:+UseParallelOldGC。GC的线程数可以通过-XX:ParallelGCThreads=<N>调整。通过-XX:MaxGCPauseMillis=<N>可以提示最大GC暂停时间,设置此参数会导致JVM自动调整Heap大小和一些JVM相关参数,慎用。 Concurrent GC,也称CMS GC,可以在Old区的回收同时,运行应用程序。-XX:+UseConcMarkSweepGC参数启动该GC。该GC还可以开启增量模式-XX:+CMSIncrementalMode 9. Hbase运维碎碎念 JVM GC Concurrent GC 暂停所有线程,标记活跃对象的root,然后恢复线程访问 使用一个或者多个CPU标记所有活跃对象,应用线程访问不受影响。 使用一个CPU标记第2步过程中有修改的对象。 暂停所有线程,标记前面2,3步过程中有修改的对象,然后恢复线程访问。 使用一个CPU,并发的将非活跃对象清除,内存释放给free list。 使用一个CPU,并发的重整heap大小,并准备下一轮GC需要的数据结构。 10. Hbase运维碎碎念 JVM GC Concurrent GC 并发GC更消耗CPU,假如有N个CPU,GC可使用1 <= K <= ceil(N/4) 。 并发GC可能造成Heap碎片,Cloudera推出了MemStore-Local Allocation Buffers特性来改善碎片问题。 如果并发GC进行中,有新对象要进入年老代会导致Concurrent Mode Failure,此时只能stop the world,改用串行Full GC。 如果新的对象要进入年老代,但年老代没有足够大小的连续空间,会导致Promotion Failuer,此时只能stop the world,进行Full GC -XX:CMSInitiatingOccupancyFraction=<N> 可以控制启动CMC GC的阀值,N表示年老代的大小百分比。如果Concurrent Mode Failure频繁出现,可以考虑降低其值。 11. Hbase运维碎碎念 JVM GC 不管哪种GC,年轻代的GC都会阻塞线程。推荐年轻代使用Parallel New GC,年老代使用CMS GC -XX:+UseParNewGC –XX:+UseConcMarkSweepGC 禁止程序显式GC -XX:+DisableExplicitGC 打印GC Log -verbose:gc -Xloggc:filename -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 打印年老代FreeListSpace的状态 -XX:PrintFLSStatistics=1 打印CMS的信息 -XX:PrintCMSStatistics=1 12. Hbase运维碎碎念 NUMA 从JDK6u2开始,增加了-XX:+UseNUMA,在 UseParallelGC时,JVM会将年轻代根据节点数切分为不同的pool。 cat /sys/devices/system/node/node0/meminfo Node 0 MemTotal: 12382196 kB Node 0 MemFree: 9739412 kB Node 0 MemUsed: 2642784 kB Node 0 Active: 1805868 kB Node 0 Inactive: 548076 kB Node 0 HighTotal: 0 kB Node 0 HighFree: 0 kB Node 0 LowTotal: 12382196 kB Node 0 LowFree: 9739412 kB Node 0 Dirty: 396 kB Node 0 Writeback: 0 kB Node 0 FilePages: 1765192 kB Node 0 Mapped: 23236 kB Node 0 AnonPages: 589204 kB Node 0 PageTables: 3672 kB Node 0 NFS_Unstable: 0 kB Node 0 Bounce: 0 kB Node 0 Slab: 141612 kB Node 0 HugePages_Total: 0 Node 0 HugePages_Free: 0 13. Hbase运维碎碎念 NUMA $ numastat node0 node1 numa_hit 1675519925 1659271911 numa_miss 0 0 numa_foreign 0 0 interleave_hit 110847 112840 local_node 1675317828 1658259635 other_node 202097 1012276 15. Hbase运维碎碎念 NUMA 关闭NUMA? vi /etc/grub.conf … Title Red Hat Enterprise Linux Server (2.6.18-164.el5) root (hd0,0) kernel /vmlinuz-2.6.18-164.el5 ro root=LABEL=/ numa=off console=tty0 console=ttyS1,115200 initrd /initrd-2.6.18-164.el5.img 16. Hbase运维碎碎念 Large Page OS设置 假设使用2G的大页面内存(2M页面) echo 1000 > /proc/sys/vm/nr_hugepages echo 2147483647 > /proc/sys/kernel/shmmax JVM设置 -XX:+UseLargePages -Xmx整个JVM Heap必须全部使用大页内存,或者全部不用。 18. Hbase运维碎碎念 ulimit sudo vi /etc/security/limits.conf * soft nproc 65536 * hard nproc 65536 * soft nofile 65536 * hard nofile 65536 Swap echo 0 > /proc/sys/vm/swappiness 19. Hbase运维碎碎念 Sync Apache官方版本的0.20.x不支持sync(hflush),有较大存在数据丢失的可能性。 如果作为Hbase的存储,需要使用CDH3版本或者自行编译 Hadoopbranch-0.20-append分支。 官方版本的HDFS只有在文件关闭后才能确保数据不丢失,如采用官方,可考虑加快Hlog的切换(hbase.regionserver.logroll.period),以尽量减少WAL日志的丢失,但会影响性能: 产生更多的小文件,影响NameNode的管理效率 更频繁的flush,Hlog超过一定数量(默认32)后会触发所有memstore的flush,影响regionserver的效率 21. Hbase运维碎碎念 Safemode dfs.safemode.threshold.pct 默认0.999,也就是blockreport阶段NN需要收到99.9%的block的report信息才能退出安全模式 dfs.safemode.min.datanodes 退出safemode前存活的最小DN数,默认0,不限制 dfs.safemode.extension 达到阀值以后等待默认30000毫秒后才正式退出安全模式 手工进入safemode $hadoopdfsadmin -safemode enter 手工退出safemode hadoopdfsadmin -safemode leave 23. Hbase运维碎碎念 监控Metrics Metrics可以写到Ganglia,或者本地文件 vi hadoop-metrics.properties #dfs.class=org.apache.hadoop.metrics.file.FileContext dfs.class=org.apache.hadoop.hbase.metrics.file.TimeStampingFileContext dfs.period=10 dfs.fileName=/tmp/dfsmetrics.log dfs.class=org.apache.hadoop.metrics.ganglia.GangliaContext31 dfs.period=10 dfs.servers=localhost:8649 注:Hadoop的FileContext没有记录timestamp,建议使用Hbase的TimeStampingFileContext 24. Hbase运维碎碎念 监控Metrics Metrics也可以同时写到Ganglia和本地文件 dfs.class=org.apache.hadoop.metrics.spi.CompositeContext dfs.arity=2 dfs.period=10 dfs.sub1.class=org.apache.hadoop.hbase.metrics.file.TimeStampingFileContext dfs.fileName=/tmp/metrics_hbase.log dfs.sub2.class=org.apache.hadoop.metrics.ganglia.GangliaContext31 dfs.servers=localhost:8649 27. Hbase运维碎碎念 Flush/Compaction/Split CompactSplitThread.java lock.lock(); try { if(!this.server.isStopped()) { // Don't interrupt us while we are working byte [] midKey = r.compactStores(); if (r.getLastCompactInfo() != null) { // compaction aborted? this.server.getMetrics().addCompaction(r.getLastCompactInfo()); } if (shouldSplitRegion() && midKey != null && !this.server.isStopped()) { split(r, midKey); } } } finally { lock.unlock(); } 28. Hbase运维碎碎念 Flush/Compaction/Split hbase.hregion.memstore.flush.size 默认64M,当一个region中所有MemStore总大小超过64M时,开始Flush。 hbase.hregion.max.filesize 默认256M,当一个StoreFile超过256M时,会启动split分裂为两个daughter region,分裂只是创建两个reference,不复制数据。 hbase.hregion.memstore.block.multiplier 默认2,当一个region所有memstore之和超过hbase.hregion.memstore.flush.size(默认64M)大小的2倍时,会强制阻塞写刷到磁盘。 29. Hbase运维碎碎念 Flush/Compaction/Split hbase.regionserver.regionSplitLimit 如果在线的region超过此数目,则不再split,默认int.MAX_VALUE(2147483647),设为1即可关闭自动split。 hbase.hstore.compactionThreshold 默认3,当一个store中的storefile超时3个时,触发compact。所以,将此值设置为int.MAX_VALUE可关闭自动compact。 hbase.hstore.blockingStoreFiles 默认7,当region中任一个store中的storefile超过7个时,会触发的compact,在compact完成之前,flush会延迟执行。如果此时更新较多,导致该region的memstore之和超过hbase.hregion.memstore.flush.size *hbase.hregion.memstore.block.multiplier,则会阻塞更新,直到Flush完成,或者hbase.hstore.blockingWaitTime(默认90s)超时,建议加大该值。 30. Hbase运维碎碎念 Flush/Compaction/Split hbase.regionserver.maxlogs 默认32,当Hlog的数量超过32个时会造成flush所有的region,不管它的memstore是否满。 hbase.regionserver.global.memstore.upperLimit 默认0.4,表示region server上所有的memstore占用的内存总和最多为MaxHeap的40%,超过则会加锁刷磁盘,一直要等到某个memstore刷到磁盘,且memstore总和下去了,才会继续, Flush是串行操作,所以对memstore多或写非常频繁的场景要特别注意。 hbase.regionserver.global.memstore.lowerLimit 默认0.35,当所有MemStore的大小超过MaxHeap的35%时,开始持续Flush,以尽量避免到upperLimit导致锁。 31. Hbase运维碎碎念 Minor Compaction Minor Compaction只合并StoreFile,不清理历史版本和删除记录 hbase.hstore.compaction.max 默认10,一次minor compaction最多只处理10个StoreFile 32. Hbase运维碎碎念 Major Compaction Major Compaction合并所有StoreFile,清理历史版本和删除记录 hbase.hregion.majorcompaction 默认86400000 毫秒=1天,同一个region两次major compaction操作的时间间隔。 如果一次minor compaction选中的StoreFile是这个region的所有StoreFile,minor compaction会自动升级为major compaction 手工触发: $hbase shell hbase(main):015:0> compact 'test' 0 row(s) in 0.2220 seconds hbase(main):016:0> major_compact 'test' 0 row(s) in 0.3240 seconds So,如果没有delete,major compaction可以不用太频繁的执行。 33. Hbase运维碎碎念 Column Family 每个CF都有一套MemStore+StoreFiless 但是同一个table的所有CF的MemStore都会在同一时间Flush(未来或许会改善),会在同一时间split, 从写的角度看,一个table最好不要设计太多的CF,各个CF之间的数据长度和更新频率尽量保持平衡,他们之间有太多的紧耦合。 从读的角度看,读取频繁的列放到一个较小的CF较有利。 CF的设计需要均衡考虑业务的读写模式。 40. Hbase运维碎碎念 Regionserver zookeeper.session.timeout 默认3分钟,也就是rs超过3分钟没有给zk消息,Master就认为rs挂了。如果gc的过程中阻塞时间超过了3分钟,那就杯具了,so。。。 hfile.block.cache.size 默认0.2,全局公用的hfile的cache,最多占用MaxHeap的20%。当数据在memstore中读取不到时,就会从这个cache里获取,当从此cache中获取不到时,就需要读取文件。当cache的block达到了这个值的85%时,即会启动evict(日志中会出现“Block cache LRU eviction”),将cache清除到75%大小,可通过日志中的“LRU Stats: ”来观察cache的命中率 41. Hbase运维碎碎念 Client hbase.client.pause 默认1000ms,客户端被阻塞或者失败后重试间隔,间隔为指数避让,即1,1,1,2,2,4,4,8,16,32,建议改下这个值,同时加大重试次数,避免split造成客户端响应时间过长以及失败率增加。 hbase.client.retries.number 默认为10次,决定了客户端的重试次数 hbase.ipc.client.tcpnodelay 默认tcp的no delay是false,建议修改为true ipc.ping.interval RPC等待服务端响应的超时时间,默认为1分钟,有点太长了,建议改成3秒(3000) 42. Hbase运维碎碎念 Compress LZO比默认的Gzip性能更好,但Gzip压缩比更高 安装lzo-2.00以上版本:http://www.oberhumer.com/opensource/lzo/download/ 到http://code.google.com/p/hadoop-gpl-compression/下载lzo相关的native库 io.compression.codecs com.hadoop.compression.lzo.LzoCodec,com.hadoop.compression.lzo.LzopCodec io.compression.codec.lzo.class com.hadoop.compression.lzo.LzoCodec 参考:http://wiki.apache.org/hadoop/UsingLzoCompression 43. Hbase运维碎碎念 Replication 是的,Hbase 0.90.0也开始支持replication了,不过目前版本bug较多。 参考:http://koven2049.iteye.com/blog/983633 图片出处:http://hbase.apache.org/docs/r0.89.20100726/replication.html 45. Hbase运维碎碎念 备份恢复 导出到本地或者HDFS hbaseorg.apache.hadoop.hbase.mapreduce.Driver export br />Tablename/desctination 导入回Hbase hbaseorg.apache.hadoop.hbase.mapreduce.Driver import br />Tablename /source 导入TSV文件(以Tab分割的文本文件) hbaseorg.apache.hadoop.hbase.mapreduce.Driverimporttsv -Dimporttsv.columns=a,b,cTablename /source 如果是csv文件,只需要加参数-Dimporttsv.separator=,即可 46. Hbase运维碎碎念 备份恢复 Hbase集群间CopyTable hbaseorg.apache.hadoop.hbase.mapreduce.CopyTable … 或者 hbaseorg.apache.hadoop.hbase.mapreduce.Drivercopytable … Hadoop集群间Copy文件 hadoopdistcp -p -update "hdfs://A:8020/user/foo/bar" "hdfs://B:8020/user/foo/baz“ Mozilla开发的Backup工具 对运行的Hbase进行做distcp会导致不一致,Mozilla为此开发了一个Backup工具 http://blog.mozilla.com/data/2011/02/04/migrating-hbase-in-the-trenches/ 47. Hbase运维碎碎念 压力测试 $ ./hbaseorg.apache.hadoop.hbase.PerformanceEvaluation Usage: java org.apache.hadoop.hbase.PerformanceEvaluation br /> [--miniCluster] [--nomapred] [--rows=ROWS] <command> <nclients> Options: miniCluster Run the test on an HBaseMiniCluster nomapred Run multiple clients using threads (rather than use mapreduce) rows Rows each client runs. Default: One million flushCommits Used to determine if the test should flush the table. Default: false writeToWAL Set writeToWAL on puts. Default: True Command: filterScan Run scan test using a filter to find a specific row based on it's value (make sure to use --rows=20) randomRead Run random read test randomSeekScan Run random seek and scan 100 test randomWrite Run random write test scan Run scan test (read every row) scanRange10 Run random seek scan with both start and stop row (max 10 rows) scanRange100 Run random seek scan with both start and stop row (max 100 rows) scanRange1000 Run random seek scan with both start and stop row (max 1000 rows) scanRange10000 Run random seek scan with both start and stop row (max 10000 rows) sequentialRead Run sequential read test sequentialWrite Run sequential write test Args: nclients Integer. Required. Total number of clients (and HRegionServers) running: 1 <= value <= 500 Examples: To run a single evaluation client: $ bin/hbaseorg.apache.hadoop.hbase.PerformanceEvaluationsequentialWrite 1 54. Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning