HBase 性能优化和最住实践

HBase 性能优化和最住实践

ColumnFamily 的优化策略

列族的名称必须是可打印字符;列族的名称和列的描述命名尽量简短,因为 HFile 中的每一行都会包含这些信息,过长的命名会浪费存储空间;不经常使用的数据分开设计和使用不同列族存储设置时分开设计;每张表不超过三个列族;列族允许数据分离,设计列族时,确保同时访问的数据尽量存储在同一个列族中,常用的信息放在同一个列族中;刷新 (Flush) 和 紧缩 (Compact) 操作是以 Region 为单位的,Compact 操作是以每个列族中 StoreFile 的数量触发的,如果某个列族非常大,在进行 Flush 时,其他列族的数据可能会被刷新出去,导致数据掉失,所以如果列族愈多,I/O 负载会愈大;Compresison、Bloom filter 和 replication 都是以列族为单位进行设置的;

[下图是列族常用的属性]

大多数列族都可以压缩,但不建议对存放 JPEG 和 PNG 等已经压缩的文件再进行压缩,压缩解码器有 GZIP、LZO、SNAPPY,选择压缩解码器需要权限压缩后的大小以及压缩时间两个因素。

1
alter  'movie' , { NAME  =>  'desc' COMPRESSION  =>  'SNAPPY' }

BlockSize 大小的优化策略

BlockSize 块尺寸用于每次读请求读取的最小数据量,大值可以提高扫描的性能,小值可以增加随机读的速度

 

BloomFilter 的优化策略

Bloom Filter 是由 Howard Bloom 在1970年提出的二进制向量数据结构,它具有很好的空间和时间效率,能检测一个元素是否属于某个集合。Bloom Filter 是一个数据结构,它可以检测某个数据片是否存在,存在的检测结果是"no" 或者是"maybe",结果 no 表示一定不存在,结果 maybe 不表示数据一定存在HBase 支持使用 Bloom Filter 改进读取性能,Bloom Filter 的好处是无需读取每个存储文件,让 RegionServer 可以忽略掉不包含某些行 (Row) 或者是行和列 (RowCol) 的文件

1
alter  'movie' , { NAME  =>  'desc' BLOOMFILTER  =>  'ROW' }

Bloom Filter 的最佳埸景是如果有大量的文件是无需读取的,因为它的目的是通过减少大量读取文件的数量来提升读取性能;批量更新数据,这样行 (Row) 分布在少数的存储文件中,Bloom Filter 不适合用于所有行 (Row) 都需耍定期更新,并且这些行分布在不同的存储文件中。虽然 Bloom Fiilter 存放在 StoreFile 中,但它不会给存储带来太大的额外负担。

 

Schema 的优化策略

设计模型的基本原理包含 Schama 设计X总了 HBase 设计的所有基本方面,其中要思考的是设计行键和列族、将数据隔离开到不同的列族、选择合适的压缩机制和块大小等,通用的设计技巧有优化索引、数据分区和一致性的 Hash 值,在设计时要充分考虑 HBase 体系结构的限制,因为在 HBase 上关联表的开销会非常大,所以应该尽可能避免 Join 操作,数据应该是反规范化设计以避免连接操作,其次行键 (RowKey) 必须更智能,以便利用排序来优代读取。在表的设计有 Tall-Narrow 和 Wide-Flat,它们两者占用的存储空间都是相同的:

  • Tall-Narrow (高瘦型),这是一种 "列很少行很多" 的设计,它的原子性更弱,因为所有数据在不同行,all-Narrow (高瘦型) 通常会把更多的细节放在行键设计上,如果你进行 scan 操作,建议使用高瘦型
  • Wide-Flat (矮胖型),这是一种 "列只有一行但有多个列" 的设计,表的行是不可以拆分,如果行非常宽,那么你可以让每个 Region 只有一行,如果你需要每一次查询多种属性的话,可以使用矮胖型

索引的选项

如果执行许多实时查询 (Ad-Hoc Query),有可能需要使用 RDBMS 系统,如果在 HBase 上要进行关联操作都需要额外的空间和运算,在关系型数据库中的索引管理是更成熟更先进,但 HBase 在大数据情况下扩展会更好,如果必须在 HBase 上进行二次索引,可以有以下方法:

  • 使用 API 运行过滤查询,但这不利于一张大表进行全表扫苗;
  • 创建一个第二索引,可以通过一个 MapReduce 作业定期更新表,或者在数据发布到集群时双写 (Dual-Write);
  • 创建汇总表 (Aggregrate Table),这适用于时间跨度大的数据,通常通过 MapReduce 作业生成,用于预先计算实时查询的数据,例如:计算表中某个值不同实例的数目,并将这些汇总的计数写入另一张表中;

 

缓存的优化策略

在 HBase 中如何配置缓存,LruBlockCache 是用于读取 OnHeap,是基于内存的缓存,当缓存达到上限时会使用 LRU (Least Recently Used) 算法来清除数据;新 BucketCache 特性允许一级(L1) 和二级(L2) 缓存,BucketCache是默认启动的;如果你是数据使用率很低或者是只用一次,可以通过手动修改列族的 BLOCKCACHE 属性为 false 来禁用数据缓存,这样可以避免很少访问的列族数据污染了缓存区。

如何配置一级和二级缓存

  1. BucketCache 特性允许设置一级缓存和二级缓存,BucketCache 缓存机制在新 HBase 版本之后是一个默认选项,一级缓存仅存储元数据信息,二级缓存仅存储列族数据;
  2. 通过设置 CACHE_DATA_IN_L1=true 来对某特定列族的数据设定为一级缓存;
  3. 通过设置 BUCKET_CACHE_COMBINED_KEY=false,可以将 BucketCache 作为一级缓存和二级缓存使用;

在配置缓存时我们需要考虑是否调用 OnHeap 或者是 OffHeap 的内存,还有使用的应用类型是 Read-Heavy 类型或者是 Write-Heavy 类型,可以通过调整缓存配置来实现性能要求。 在生产环境下建议给 HBase Master JVM 分配 1G 的内存,给 HBase Region Server JVM 分配 12G~16G 的内存, 如果较大的 Heap 尺寸会导致较长时间的 GC 垃圾回收时间,剩馀的系统内存用于 Kernel 的缓存,可以在 hbase-env.sh 里进行内存设置配置

1
2
export  HBASE_REGIONSERVER OPTS= "-Xmx12g -Xms12g -Xmn128m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70"
export  HBASE_MASTER_OPTS= "-Xmx1000m"

 

数据倾斜导致的热点问题以及优化策略

当只有很少的 RegionServer 处理绝大多数工作负载时就会发生热点问题,因为这会导致集群资源使用不均,行键如果顺序或者是时间序列就有可能导致热点,因为这会导致写出数据都是在同一个 Region 中,如果能够把数据倾斜的数据打散就有可能解决热点问题,以下是几个解决数据倾斜的热点方案:

  • 加 salt:在真正的数据前面放一个较小的 Hash 计算后的值,以便将行键 RowKey 随机打散,e.g. <salt><timestamp> 
  • 字段前置:将行键 RowKey 后面的内容移到递增或者是时间戳字段之前,e.g. <sourceid><timestamp>
  • 伪随机数:使用 MD5 之类的单向 HASH 值对数据进行处理:<md5(timestamp)>

 

Region 预拆分的优化策略

在实际生产环境下是不建议 Region 的数量过少,RegionServer 建议为 20 到小几百个 Region 服务,因为一个 RegionServer 上如果有过大的 Region 会导致扩展问题。每个 RegionServer 服务的 Region 并不是显式配置的,这是由数据量和最大 Region 的大小所决定的。公式是:Region 拆分大小等于该服务器上同一张表的 Region 个数的平方乘以 Region Flush Size 或者设置的最大 Region 拆分大小,取两者之中较小的值。可以修改 hbase.hregion.max.filesize 来决定 Region 的拆分大小,建议 10GB。

Region 预拆分的效果

通过 Region 预拆分来提高 HBase 的性能,预拆分后数据量加载效率更高,以下是创建预拆分 Region 的例子:

1
CREATE  'myTable' 'cf1' 'cf2' , {SPLIT => [ 'A' , 'M' , 'Z' ]}

例如向一个新表中的批量加载 100GB 的数据,filsize 初始值为 10GB,当进行预拆分 Region 后,这样每个 Region 都可以得到10GB数据,如果要增加更多数据,可以预拆分成 10-20 个 Region,这样可以避免随著数据的增加而出现自动拆分。预拆分 Region 是离线处理过程,Region 会在拆分的过程中短暂离线,手工拆分 Region 可以减少表的热点问题,如果想停用预拆分 Region 功能,可以对参数 hbase.hregion.max.filesize 设置一个较大的值,比如 100GB,但要注意后续要继续启用拆分,Region 是可以合并在一起,可以利用 HBase Shell 的 merge_region 命令在线完成合并。

猜你喜欢

转载自blog.csdn.net/qq_24365213/article/details/79380208