本文主要介绍在压测HBase的二级索引phoenix时踩的一个坑,使用时需要特别注意,而且背后的原因也很有意思,可以看出HBase和Phoenix对元数据设计上的差异。

1.问题介绍

在做phoenix压测时发现一个奇怪的现象。

压测请求分布非常均匀,但是有一台机器的流量、负载都明显高于其他机器。

如下图所示。

请求均匀

资源利用率不均匀,单个节点明显偏高。

2.排查思路

看到这个问题的第一反应,是去看下表分布是否均匀。

  • hbase表分布是否均匀
  • 索引表分布是否均匀

令人遗憾的是,确认后hbase表和索引表都是均匀分布的,各个机器上的region数量、存储用量都是一致,非常均匀。

然后在网上查相关资料,在官网上看到这样一段描述。(http://phoenix.apache.org/language/index.html)

UPDATE_CACHE_FREQUENCY option (available as of Phoenix 4.7) determines how often the server will be checked for meta data updates (for example, the addition or removal of a table column or the updates of table statistics). Possible values are ALWAYS (the default), NEVER, and a millisecond numeric value. An ALWAYS value will cause the client to check with the server each time a statement is executed that references a table (or once per commit for an UPSERT VALUES statement). A millisecond value indicates how long the client will hold on to its cached version of the metadata before checking back with the server for updates.

大致的意思是,phoenix的表设计时有一个表级别参数UPDATE_CACHE_FREQUENCY,这个参数默认是ALWAYS,表示每次sql查询都会先去请求meta数据。也可以设置为一定频率,表示多久去请求一次meta数据。

那我们大概能猜想到了,因为设计表的时候没有指定这个参数,所以为默认的always,而phoenix的meta数据正好落在了那个机器上。

我们查验了下系统表的位置,果然如此!

于是立刻做了变更

alter table xxx set UPDATE_CACHE_FREQUENCY = xxxxx。

  效果显著!

不仅流量、负载均匀了,而且整体负载下降了很多!!!

那为什么监控上请求量是均匀的呢?因为phoenix需要访问catalog表,然后这个表刚才在core-2上,访问这个表走的coprocessor,所以没统计出请求数。

3.进一步思考

到上面为止,问题的原因找到了,也解决了。

但是熟悉HBase的同学肯定会马上有个疑问,跟我一样。为什么会有这样一个参数设置,HBase本身也有meta表,而HBase的meta表在客户端缓存就可以。

下面,就让我们来思考下。

1)phoenix为什么要这么设计呢,而不是像hbase的meta表一样?

这个问题得从phoenix的架构设计说起。

phoenix一直以来,都是重客户端模式,即使是现在的轻客户端版本,本质也是如此。只不过把客户端放在了query server这个角色上,让query server跑在服务端了。

但对hbase来说,phoenix的核心逻辑都在client侧。元数据管理也是如此。phoenix和HBase不同的是,phoenix的元数据更复杂,如果元数据有变化,没有拿到最新meta的客户端不一定会抛错。

举个例子,比如一个查询命中索引后会更高效。但是,某个客户端它 不知道有这个索引表,于是就去查了主表,这个在phoenix上看也没有毛病。

所以,关键原因是phoenix无法感知元数据是否发生了变化!而HBase可以。

因此,最初为了解决元数据同步的问题,就采用了比较激进的每次刷新的方式。后来发现会影响性能,就加了一个周期性刷新的功能,来避免per request去刷meta数据。

2)那可以alter table时触发meta更新吗?

这个是不可以的。因为客户端可能比较多。而且,也不会有一个地方去记录全局有哪些client。即使有这样一个地方,那某个client挂了怎么办?没有通知成功怎么办?此时,alter操作是成功还是不成功呢?

3)结论

所以这个参数是phoenix的设计,而不是缺陷。phoenix默认情况下,每个请求都会去校验一次表的元数据信息,以避免因meta未刷新导致失败。为此,phoenix提供了一个表参数,来控制meta的刷新频率,比如1分钟刷一次,类似这种。

可以在建表的时候设定:

craete table if not exists ns.table_demo (
id varchar not null primary key,
f1.a varchar,
f1.b varchar,
f1.c varchar
)
TTL=86400,
UPDATE_CACHE_FREQUENCY=900000;

也可以变更表结构设定:

alter table xxx set UPDATE_CACHE_FREQUENCY = xxxxx; 

设一个你期望的刷新时间,就可以解决问题了。

当然,这样带来的副作用就是,如果未来你修改了这个表,比如add了一个新的列,或者新加了一个索引,最少要等待一个刷新周期才能生效。但是无关大局,一般表结构变更就属于低频操作,而且能够接受一定延迟。

看到这里了,原创不易,点个关注、点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

使用phoenix踩的坑与设计思考的更多相关文章

  1. 一次flume exec source采集日志到kafka因为单条日志数据非常大同步失败的踩坑带来的思考

    本次遇到的问题描述,日志采集同步时,当单条日志(日志文件中一行日志)超过2M大小,数据无法采集同步到kafka,分析后,共踩到如下几个坑.1.flume采集时,通过shell+EXEC(tail -F ...

  2. Phoenix踩坑填坑记录

    Phoenix踩坑填坑记录 Phoenix建表语句 如何添加二级索引 判断某表是否存在 判断索引是否存在 Date类型日期,条件判断 杂项 记录Phoenix开发过程中的填坑记录. 部分原文地址:ph ...

  3. 使用CCNode作为容器容易踩的坑

    Cocos2dx中CCNode经常作为一个父容器,里面装一些UI控件,最后组成一个复杂的自定义的UI控件,但是在使用别人的自定义控件和自己写自定义问题的时候会踩一些坑. 首先拿到一个自定义的UI控件一 ...

  4. Asp.Net Core中使用Swagger,你不得不踩的坑

    很久不来写blog了,换了新工作后很累,很忙.每天常态化加班到21点,偶尔还会到凌晨,加班很累,但这段时间,也确实学到了不少知识,今天这篇文章和大家分享一下:Asp.Net Core中使用Swagge ...

  5. java基础不牢固容易踩的坑

    java基础不牢固容易踩的坑 经过一年java后端代码以及对jdk源码阅读之后的总结,对java中一些基础中的容易忽略的东西写下来,给偏爱技术热爱开源的Coder们分享一下,避免在写代码中误入雷区. ...

  6. 从零开始学 Java - Spring 支持 CORS 请求踩的坑

    谁没掉进过几个大坑 记得好久之前,总能时不时在某个地方看到一些标语,往往都是上面一个伟人的头像,然后不管是不是他说的话,下面总是有看起来很政治正确且没卵用的屁话,我活到目前为止,最令我笑的肚子痛得是下 ...

  7. 用thinkphp进行微信开发的整体设计思考

    用thinkphp进行微信开发的整体设计思考 http://www.2cto.com/weixin/201504/388423.html 2015-04-09      0个评论       作者:明 ...

  8. webuploader插件,我踩得坑

    我在目前的公司做的项目要么是原生写法去做项目,要么就是vue+webpack做项目,但是vue这部分只是用了模板template,vue其他的都没用. 有一个项目需要做上传图片的功能,老大扔给我一个插 ...

  9. 谈谈调用腾讯云【OCR-通用印刷体识别】Api踩的坑

    一.写在前面 最近做项目需要用到识别图片中文字的功能,本来用的Tesseract这个写的,不过效果不是很理想. 随后上网搜了一下OCR接口,就准备使用腾讯云.百度的OCR接口试一下效果.不过这个腾讯云 ...

随机推荐

  1. [redis]SDS和链表

    一.SDS 1.SDS结构体 redis3.2之前:不管buf的字节数有多少,都用 4字节的len来储存长度,对于只存短字符串那么优点浪费空间,比如只存 name,则len=4 则只需要一个字节8位即 ...

  2. jdbc批量插入数据

    //插入很多书(批量插入用法) public void insertBooks(List<Book> book) {   final List<Book> tempBook=b ...

  3. RANet : 分辨率自适应网络,效果和性能的best trade-off | CVPR 2020

    基于对自适应网络的研究,论文提出了自适应网络RANet(Resolution Adaptive Network)来进行效果与性能上的取舍,该网络包含多个不同输入分辨率和深度的子网,难易样本的推理会自动 ...

  4. python实现逻辑回归

    首先得明确逻辑回归与线性回归不同,它是一种分类模型.而且是一种二分类模型. 首先我们需要知道sigmoid函数,其公式表达如下: 其函数曲线如下: sigmoid函数有什么性质呢? 1.关于(0,0. ...

  5. 多线程并行请求问题及SplashActivity预加载问题解决方案

    1. 问题描述(一): 现有3个线程thread1, thread2, thread3.这3个线程是并发执行的,当着3个线程都执行完成以后,需要执行一个finish()事件. 1.1 实现方法: /* ...

  6. 徐州A

    #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...

  7. Netty(七):EventLoop学习前导——Reactor模式

    了解Netty的人多少都会知道Netty的高性能的一个原因就是它是基于事件驱动的,而这一事件的原型就是Reactor模式. 所以在学习EventLoop前,很有必要先搞懂Reactor模式. 本文目录 ...

  8. Codeforce1311B. WeirdSort (冒泡排序)

    You are given an array a of length n. You are also given a set of distinct positions p1,p2,-,pm, whe ...

  9. 补题Codeforces 1102E. Monotonic Renumeration

    这个题还是不太懂,下面附上的是大佬的题解(https://zhanghuimeng.github.io/post/codeforces-1102e-monotonic-renumeration/) E ...

  10. Java自动装箱与缓存

    自动装箱与缓存 现象 有以下代码: 1 public class Main { 2 public static void main(String[] args) { 3 Integer i1 = 12 ...