Poison


  • 首页

  • 归档

  • 标签

  • 搜索
close
Poison

Hive #1611

发表于 2021-07-31

在每日的数据同步任务中,会将在线业务库的数据同步至 Hive,在刚上线的一段时间内,对 Hive 的 SQL 操作每隔十来天会出现 socket read timeout 的异常,该问题导致我经常凌晨收到告警然后起床修复该问题,因为该问题是偶现,不便复现,经过查阅 Hive JDBC 的源码,定位问题为 Hive JDBC 使用了 java.sql.DriverManager 中的静态变量 loginTimeout 的值,而我们的工程中接入了八九种类型的 JDBC 驱动,部分类型还使用了连接池,先看看 java.sql.DriverManager 中的部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class DriverManager {
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
// 该变量被声明为 static, 导致其他类型的数据源设置了 DriverManager 中的该变量后,Hive JDBC 将会使用到其他类型数据源设置的超时时间
private static volatile int loginTimeout = 0;
private static volatile java.io.PrintWriter logWriter = null;
private static volatile java.io.PrintStream logStream = null;
// Used in println() to synchronize logWriter
private final static Object logSync = new Object();

/* Prevent the DriverManager class from being instantiated. */
private DriverManager(){}

/**
* Sets the maximum time in seconds that a driver will wait
* while attempting to connect to a database once the driver has
* been identified.
*
* @param seconds the login time limit in seconds; zero means there is no limit
* @see #getLoginTimeout
*/
public static void setLoginTimeout(int seconds) {
loginTimeout = seconds;
}

/**
* Gets the maximum time in seconds that a driver can wait
* when attempting to log in to a database.
*
* @return the driver login time limit in seconds
* @see #setLoginTimeout
*/
public static int getLoginTimeout() {
return (loginTimeout);
}

// ...
阅读全文 »
Poison

OutOfMemoryError

发表于 2021-07-31

关于 JVM 应用的 OOM,首先可以阅读 Oracle 的文档:3.2 Understand the OutOfMemoryError Exception,根据我的经验,大部分都是开发人员的代码问题导致,而关于出现了 OOM 是否应该及时终止应用在 Oracle 的文档中好像也没有明确的说明,但是在 Stack Overflow 上有不少讨论,如:Can the JVM recover from an OutOfMemoryError without a restart,最高票的回答表明 OOM 发生后不是一定要及时终止应用,但是建议终止应用,因为 OOM 后应用可能存在不一致的状态。

阅读全文 »
Poison

关于 RoaringBitmap 的线程安全问题

发表于 2021-07-31

对于一个数据结构,如果作者没有表明该数据结构是线程安全的,我一般都会认为不是线程安全的,因为编写高效且线程安全的数据结构是比较困难的,关于 RoaringBitmap 的线程安全问题,早在 2015 年就有用户反馈希望能够有线程安全的实现,详见该 issue: thread safety,仅有几次提交后至 2017 年后就再无下文,而 RoaringBitmap 的主线一直在演进,且在官方文档中甚至没有关于线程安全实现的介绍,以至后续在我的工程中,关于 RoaringBitmap 的并发修改使用了 ReentrantReadWriteLock 去保证多线程下的线程安全,使用读写锁是为了提高读多于写场景下的吞吐量。

阅读全文 »
Poison

ShedLock

发表于 2021-07-30

在 Java 应用中,经常会使用 Spring 的 @Scheduled 注解用于处理定时任务,但是在集群环境中,这会导致被 @Scheduled 注解标记的方法在每个应用节点都被定时执行,在早期的工程代码中,开发使用一个定时任务 IP 去指定执行任务的节点 IP,若当前节点 IP 与指定的定时任务 IP 一致才执行定时任务,该方案需要在每个 @Scheduled 方法中硬编码 IP 判断逻辑,且在部分应用迁移至 k8s 后因节点 IP 不确定导致该方案不再可用,故查询了下相关的解决方案。

我们在部分工程引入了 ShedLock 用于处理分布式环境下的定时任务重复执行的问题,下面简单记录一下 ShedLock 的实现机制。

阅读全文 »
Poison

OuterJoinBehavior

发表于 2021-07-22

业务方反馈有一条 SQL 在 Hive on Spark 上执行会触发 OOM,原 SQL 经简化后如下:

1
SELECT c.name, COUNT(DISTINCT u.user_id) AS `uv`, COUNT(*) AS `pv` FROM u LEFT JOIN w ON get_json_object(u.param, '$.id') = w.id LEFT JOIN c ON w.cat_id = c.id WHERE u.page = 'xxx.htm' AND c.name LIKE '%筛选%' AND u.dt >= '20210715' GROUP BY c.name ORDER BY `pv` DESC LIMIT 10;

其中 u.dt 为 u 表的分区列,按照该 SQL 的含义,即只需要扫描大于等于 20210715 的分区数据,但是通过检查 SQL 执行计划可视化图及查看逻辑计划,发现 u.dt 的筛选条件并没有下推至 u 表,而是在将 u 表与 w 表进行 LEFT JOIN 后再进行了过滤,导致扫描了整张 u 表,而又因为 u 表相当大,最后触发了 OOM,随后查询 Hive 关于外连接 JOIN 行为的文档:OuterJoinBehavior - Apache Hive - Apache Software Foundation,该文档详细描述了什么时候可以执行谓词下推,什么时候不能执行谓词下推,但是,所有的例子都是两张表时的示例,并没有解释多张表时的谓词下推规则,根据该文档的描述,我们把 SQL 调整为先 LEFT JOIN 其中两张表为临时表再进行一次 LEFT JOIN 后,成功进行了谓词下推,解决了该问题。

如,以下两种写法都进行了谓词下推:

1
2
3
SELECT c.name, COUNT(DISTINCT u.user_id) `uv`, COUNT(*) AS `pv` FROM (SELECT u.user_id, w.cat_id FROM u LEFT JOIN w ON get_json_object(u.param, '$.id') = w.id WHERE u.dt >= '20210715' AND u.page = 'xxx.htm') LEFT JOIN c ON w.cat_id = c.id AND c.name LIKE '%筛选%' GROUP BY c.name ORDER BY `pv` DESC LIMIT 10;

SELECT t.name, COUNT(DISTINCT u.user_id) AS `uv` , COUNT(*) AS `pv` FROM u LEFT JOIN (SELECT w.id, c.name FROM w w LEFT JOIN cat c ON w.cat_id = c.id WHERE c.name LIKE '%筛选%') t ON get_json_object(u.param, '$.id') = t.id WHERE u.dt >= '20210715' AND u.page = 'xxx.htm' GROUP BY t.name LIMIT 10;
2021-12-02

今天阅读 《Spark SQL内核剖析》 时发现在第 11 章的 “SQL 写法的陷阱” 第三小节中举的例子即为以上引用到的链接中的内容:OuterJoinBehavior - Apache Hive - Apache Software Foundation。

Reference

《Hive 编程指南》
Understanding Spark’s Logical and Physical Plan in layman’s term

1…202122…26

130 日志
119 标签
GitHub LeetCode
© 2025 Poison 蜀ICP备16000644号
由 Hexo 强力驱动
主题 - NexT.Mist