Jetty导致Presto堆外内存泄露的排查过程

背景

一个Presto集群报警,显示Coordinator内存不足。看了下,发现RES内存(86.7G) > XMX(72G) + 堆外内存(10G),然后看了下Presto UI里Resource Utilization的Non-Heap Memory Used,只用了200M。问题奇怪,pmap查看进程的内存映像信息,如下:

1
2
3
4
5
6
7
8
9
10
11
[presto@hostname ~/presto-current]$ pmap -x 107870 | sort -rn -k3 | head -n 10
total kB 106752092 86763996 86684760
00007fd673000000 75644928 61078708 61078708 rw--- [ anon ]
00007fd5c8000000 2654208 2537116 2537116 rw--- [ anon ]
000000000120a000 1244772 1244644 1244644 rw--- [ anon ]
00007fd5803cf000 520388 497972 497972 rw--- [ anon ]
00007fd08c836000 149720 149720 149720 rw--- [ anon ]
00007fd0e2fe2000 147620 147620 147620 rw--- [ anon ]
00007fd0d9b35000 146920 146920 146920 rw--- [ anon ]
00007fe964000000 116672 114164 114164 rwx-- [ anon ]
00007fd0612b1000 111932 111932 111932 rw--- [ anon ]

第一列表示虚拟空间地址,第二列表示该项在虚拟空间中占用的大小,第三列表示RSS,第四列表示DIRTY,第五列表示该项名称(anon是佚名的)。

jmap -heap 发现堆内内存占用正常,然后我jmap dump了一份内存,dump后发现只有700M+,应该与堆内存无关了,既然这样查找直接从堆外内存入手了。

Read More

记一次Presto Worker OOM的查找过程

背景

最近Presto集群又上线了几个新业务,伴之而来的是OOM很频繁,且发生时间多在早晨8点左右,线上稳定性是高优需要解决的,所以查找了下导致Presto集群OOM的原因,发现了一些问题,这里抛砖引玉下,可能其他使用Presto的用户也会遇到类似的问题。

排查过程

我给一些业务划分了不同的label,这里说明下我们把Presto引擎改进了下,可以动态将机器划分不同的label,这样SQL查询时候指定不同的label,SQL调度时只根据指定的label查找机器即可。之后发现一个业务方的SQL会导致集群OOM。具体表现为,多次Full GC,之后OOM,看GC日志第一感觉应该是有内存泄露。

我通过审计日志(之前通过event-listener实现了个日志审计模块)拿到OOM时2K左右条SQL,发现SQL都是简单的SQL,类似这种:

1
SELECT * FROM table WHERE year='2020' AND month='06' AND day='01' LIMIT 10;

根据SQL,我猜测可能以下2种原因导致了OOM:

  • 查询的表存在Hive视图(我让Presto支持了Hive视图)
  • 异常SQL触发了内存泄露

Read More

PrestoDB和PrestoSQL比较及选择

Presto 社区分家后搞了2个项目,分别为 PrestoDB 和 PrestoSQL,同时他们都成立了自己的基金会。而去年国庆时候,abei写了篇文章比对了2个分支的进展,链接见:PrestoDB VS PrestoSQL发展比较。 而现在已经分家17个月了,那我们简单梳理下这2个分支的主要核心功能:

PrestoDB:

  • Connector:ElasticSearch 及 Druid
  • Master 和Worker 通信协议支持二进制
  • Orc 及 Parquet读写性能优化
  • Hive写数据支持指定压缩格式
  • task通信协议可以指定 thrift
  • spi pushdown
  • MapReduce-style shuffle,支持部分 etl 任务及大查询
  • fix bug 及 improve performace

PrestoSQL:

  • Connector:ElasticSearch和MemSQL
  • spi pushdown
  • S3优化读取
  • join 延时物化
  • 大量的 fix bug 及 improve performance

Read More

Presto调度task选择Worker方法

Presto调度task方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
public final class SystemPartitioningHandle
implements ConnectorPartitioningHandle
{
private enum SystemPartitioning
{
SINGLE,
FIXED,
SOURCE,
SCALED,
COORDINATOR_ONLY,
ARBITRARY
}
}

常见的场景主要包含SINGLE、FIXED及SOURCE类型,其中SINGLE表示最后数据的汇总输出,FIXED表示中间数据的计算,如JOIN等,SOURCE类型表示与源数据打交道的类型。

以下SQL为例:

1
select * from (select * from 1test join 2test1 on 1test.id = 2test1.123id);

Read More

Presto集群内存不足时保护机制

为了防止集群里节点OOM,Presto有个循环线程来获取当前集群节点和集群整体内存占用情况。通过这篇文章:Presto内存管理相关参数设置 我们知道Presto里分为RESERVED_POOL和GENERAL_POOL。

判断节点是否阻塞(内存不足):

如果使用RESERVED_POOL(意思是说最大SQL使用这个POOL),那判断集群内存超出内存的方法就是:

1、RESERVED_POOL内存被SQL占用了

2、GENERAL_POOL里有被阻塞的Node

因为RESERVED_POOL会导致内存浪费,我们集群配置参数没有使用这个POOL,只使用了GENERAL_POOL,所以只需要查看下GENERAL_POOL是怎么判断节点是否Block住的。

1
2
3
if (poolInfo.getFreeBytes() + poolInfo.getReservedRevocableBytes() <= 0) {
blockedNodes++;
}

getReservedRevocableBytes 这个是用于获取spill到磁盘的内存,目前我们集群是不允许内存Spill到磁盘的,因为Presto面向的是ad-hoc场景,要求是快,如果说需要spill到磁盘,那spark是一个更好的选择,且早期版本Presto spill到磁盘之前测试过稳定性比较差,场景也比较少。

所以就判断GENERAL_POOL里是否还有剩余内存,如果小于等于0,那就表示该节点是个Block状态。

Read More

Presto内存管理相关参数设置

背景

之前介绍过Presto内存管理和分配策略,但是那个是0.192版本,详细见:Presto内存管理原理和调优 ,0.201之后内存管理作了新的修改,所以重新简单分析下,然后给出一个配置模板,希望对使用Presto的同学有帮助。

两种内存

Presto里面内存只有2种内存,一种是user memory,另一种是system memory。system memory用于input/output/exchange buffers等,user memory 用于hash join、agg这些。

内存池

0.201之前有3种内存POOL,分别是GENERAL_POOL、RESERVED_POOL及SYSTEM_POOL。但是0.201之后,默认SYSTEM_POOL是不开启的,以下参数控制,默认值为false

1
deprecated.legacy-system-pool-enabled

那SYSTEM_POOL不使用了,这块内存怎么控制呢,去代码里确认了下:

Read More

Presto ORC及其性能优化

简介

ORC的全称是(Optimized Row Columnar),其是为了加速Hive查询以及节省Hadoop磁盘空间而生的,其使用列式存储,支持多种文件压缩方式。由于其被广泛应用在Hadoop系统中,Presto 0.77版本在Hive Connector里实现了ORC Reader。

ORC文件结构

上图(图1)来自网络,有很多文章通过这张图片介绍了ORC文件结构,我这里就不多啰嗦了,我们直接通过数据来看文件格式吧。

Read More