[HBase] - 一次由 Hive HBase 外部表引发的读性能问题

1 问题

近期业务反馈 HBase GET 读性能不佳,查看监控,每天有几个时间波段,GET P99 请求时延很高。

2 问题原因

定位有一个业务有 7 张 Hive HBase 外部表,每天有两个时间定时通过 sql 的方式,并发导出全表到 hive 。代码类似于:

 insert into table_hive select * from hive_hbase_external_table;

相当于每天定时并发对 7 张大的 HBase 全表 ScanScan 默认会写缓存,这个会导致:

  1. Bucket Cache 被 scan block 写满, 缓存开始淘汰,出现 cache miss (缓存命中率降低) 和 cache eviction (缓存淘汰)。cache 命中率直接影响 HBase 读性能。
  2. 出现 I/O 风暴,读请求没有命中缓存需要读 hdfs,此时由于 I/O 瓶颈,读性能问题进一步被放大。

3 问题分析

查看这几个时间段 GET 请求没有明显变多(单节点 1k/s),而 READ 请求猛增,单节点 read request 达到 600-900k/s。

推断是出现了大量 scan 或者大 scan。这里为什么要推理,因为 Ambari grafana 的 HBase scan 请求数无法显示。

缓存命中率直接影响读性能,查看 BucketCache 命中率情况,这个时间段 cache miss 和 eviction 都陡增。
缓存

推断是 scan 导致缓存写满,所以出现缓存被驱逐(eviction)。

没有命中缓存,就会走 hdfs,查看 datanode 监控有大量的 block read,查看 datanode 磁盘监控,磁盘 I/O 这段时间被打满。
datanode 磁盘

大量的读导致了磁盘瓶颈,读性能更差了

到这里,剩下的就是揪出是谁在进行大 Scan 操作,HBase 上承载的业务众多,一个个问业务不太现实。
于是通过热点 Regionserver 节点的日志看到该时间段,有一些 Scan 的报错,找到表名,拿去一问业务就问出来问题了。(这种方式着实有点原始)。
业务每天定时并发对 7 张 HBase 大表进行全表 Scan,查询导出数据到 Hive。

4 Hive HBase 外部表使用与坑

创建 HBase 的 hive 外部表典型建表语句如下,rowkey 字段为 hbase 的 rowkey,label 为列族:

CREATE EXTERNAL TABLE user_profile.mix_label_scene_tag_test_1(rowkey string COMMENT 'rowkey', label map<string,string> COMMENT 'cf')
ROW FORMAT SERDE 'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES('hbase.columns.mapping'=':key,label:')
TBLPROPERTIES('hbase.table.name'='profile:mix_label_scene_tag_pre_release')

HBase 相关的参数可以直接通过 set 的方式配置进去,例如:

set hbase.client.scanner.timeout.period=600000;

但是这里有一个坑需要注意,默认 hive hbase 外部表 scan 是会缓存 block 的,这个不容易被开发注意到。如果有大量的 scan 类型的批处理、 mr 任务等,会对缓存是一种破坏性的写入。影响其他正常读请求。HBase 官方也有建议,针对批处理类型的 scan 操作,要设置 setCacheBlocks 为 false:

Scan instances can be set to use the block cache in the RegionServer via the setCacheBlocks method. For input Scans to MapReduce jobs, this should be false. https://hbase.apache.org/book.html#perf.hbase.client.blockcache

Hive 社区也有人提了这个问题 HIVE-20484,在 Hive 3 以上的版本进行了修复,将外部表 scan.setCacheBlocks 默认设为 false。hive 这块的代码如下:

public static final String HBASE_SCAN_CACHEBLOCKS = "hbase.scan.cacheblock";

...

String scanCacheBlocks = tableProperties.getProperty(HBaseSerDe.HBASE_SCAN_CACHEBLOCKS);
if (scanCacheBlocks != null) {
  jobProperties.put(HBaseSerDe.HBASE_SCAN_CACHEBLOCKS, scanCacheBlocks);
}

...

String scanCacheBlocks = jobConf.get(HBaseSerDe.HBASE_SCAN_CACHEBLOCKS);
if (scanCacheBlocks != null) {
  scan.setCacheBlocks(Boolean.parseBoolean(scanCacheBlocks));
}

如果没法升级 hive ,解决办法有两个:

  1. 重新创建外部表,SERDEPROPERTIES 里指定: 'hbase.scan.cacheblock'='false',这种方式可以屏蔽 scan 写缓存,又保留正常的 get 读缓存。
CREATE EXTERNAL TABLE user_profile.mix_label_scene_tag(rowkey string COMMENT 'rowkey', label map<string,string> COMMENT 'cf')
ROW FORMAT SERDE 'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES('hbase.columns.mapping'=':key,label:','hbase.scan.cacheblock'='false')
TBLPROPERTIES('hbase.table.name'='profile:mix_label_scene_tag_pre_release')
  1. 修改表的属性,修改列族的缓存策略,这种方式全局屏蔽读缓存,会影响正常的 get 读写缓存
alter 'profile:mix_label_scene_tag', {NAME => 'label', BLOCKCACHE => 'false'}

值得一提的是,setCacheBlocks 是设置:是否把读取的数据写入到缓存中。所以不管怎么设定 setCacheBlocks 的 bool 值,HBase 默认的读请求都会先查缓存。

4.1 Hive HBase 外部表相关参数

附上其他的配置,源码

 public static final String HBASE_COLUMNS_MAPPING = "hbase.columns.mapping";
  public static final String HBASE_TABLE_NAME = "hbase.table.name";
  public static final String HBASE_TABLE_DEFAULT_STORAGE_TYPE = "hbase.table.default.storage.type";
  public static final String HBASE_KEY_COL = ":key";
  public static final String HBASE_TIMESTAMP_COL = ":timestamp";
  public static final String HBASE_PUT_TIMESTAMP = "hbase.put.timestamp";
  public static final String HBASE_COMPOSITE_KEY_CLASS = "hbase.composite.key.class";
  public static final String HBASE_COMPOSITE_KEY_TYPES = "hbase.composite.key.types";
  public static final String HBASE_COMPOSITE_KEY_FACTORY = "hbase.composite.key.factory";
  public static final String HBASE_STRUCT_SERIALIZER_CLASS = "hbase.struct.serialization.class";
  public static final String HBASE_SCAN_CACHE = "hbase.scan.cache";
  public static final String HBASE_SCAN_CACHEBLOCKS = "hbase.scan.cacheblock";
  public static final String HBASE_SCAN_BATCH = "hbase.scan.batch";
  public static final String HBASE_AUTOGENERATE_STRUCT = "hbase.struct.autogenerate";
  /**
   * Determines whether a regex matching should be done on the columns or not. Defaults to true.
   * <strong>WARNING: Note that currently this only supports the suffix wildcard .*</strong>
   */
  public static final String HBASE_COLUMNS_REGEX_MATCHING = "hbase.columns.mapping.regex.matching";
  /**
   * Defines the type for a column.
   **/
  public static final String SERIALIZATION_TYPE = "serialization.type";

  /**
   * Defines if the prefix column from hbase should be hidden.
   * It works only when @HBASE_COLUMNS_REGEX_MATCHING is true.
   * Default value of this parameter is false
   */
  public static final String HBASE_COLUMNS_PREFIX_HIDE = "hbase.columns.mapping.prefix.hide";

5 todo

HBase 怎么提升缓存命中率,除了缓存命中率,还有什么会影响读性能?
HBase 如何监控大 Scan?
HBase 如何进行表级别的监控?
HBase Hive 外部表如何有效监控管理,避免用户随意 scan 操作?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容