presto内存管理及调优

内存池

Presto有三种内存池,分别为GENERAL_POOL、RESERVED_POOL、SYSTEM_POOL。这三个内存池占用的内存大小是由下面算法进行分配的:

builder.put(RESERVED_POOL, new MemoryPool(RESERVED_POOL, config.getMaxQueryMemoryPerNode()));

builder.put(SYSTEM_POOL, new MemoryPool(SYSTEM_POOL, systemMemoryConfig.getReservedSystemMemory()));

long maxHeap = Runtime.getRuntime().maxMemory();
maxMemory = new DataSize(maxHeap - systemMemoryConfig.getReservedSystemMemory().toBytes(), BYTE);
DataSize generalPoolSize = new DataSize(Math.max(0, maxMemory.toBytes() - config.getMaxQueryMemoryPerNode().toBytes()), BYTE);
builder.put(GENERAL_POOL, new MemoryPool(GENERAL_POOL, generalPoolSize));

梳理这块代码对应的逻辑和配置文件,得出RESERVED_POOL大小由config.properties里的query.max-memory-per-node指定;SYSTEM_POOL由config.properties里的resources.reserved-system-memory指定,如果不指定,默认值为Runtime.getRuntime().maxMemory() * 0.4,即0.4 * Xmx值;而GENERAL_POOL值为 总内存(Xmx值)- 预留的(max-memory-per-node)- 系统的(0.4 * Xmx)。

而这三种内存池分别用于不同的地方,分析代码和阅读Presto开发手册,大体可以定位出:

  • GENERAL_POOL is the memory pool used by the physical operators in a query.
  • SYSTEM_POOL is mostly used by the exchange buffers and readers/writers.
  • RESERVED_POOL is for running a large query when the general pool becomes full.

简单说GENERAL_POOL用于普通查询的physical operators;SYSTEM_POOL用于读写buffer;而RESERVED_POOL比较特殊,大部分时间里是不参与计算的,只有当同时满足如下情形下,才会被使用,然后从所有查询里获取占用内存最大的那个查询,然后将该查询放到 RESERVED_POOL 里执行,同时注意RESERVED_POOL只能用于一个Query。

1、GENERAL_POOL有节点出现阻塞节点(block node)情况,即该node内存不足
2、RESERVED_POOL没有被使用

GENERAL_POOL、RESERVED_POOL、SYSTEM_POOL应配合合理的值,如果并发比较大时,建议SYSTEM_POOL保持默认或者稍微再大一点。目前我的经验配置是SYSTEM_POOL为1/3 * Xmx(虽然我们并发较多,但是依然调低了此值);RESERVED_POOL 为 1/9 * XMX。

当然你可以通过HTTP请求查看每台Worker的/v1/status,来预估具体需要配置多大的内存,如图所示,显示了各内存池的使用量。

http://10.84.99.3:8080/v1/status
{
    "nodeId": "10-84-99-3", 
    "nodeVersion": {
        "version": "2bcd31d-dirty"
    }, 
    "environment": "product", 
    "coordinator": true, 
    "uptime": "13.23d", 
    "externalAddress": "10.84.99.53", 
    "internalAddress": "10.84.99.53", 
    "memoryInfo": {
        "totalNodeMemory": "35433480192B", 
        "pools": {
            "reserved": {
                "maxBytes": 10737418240, 
                "reservedBytes": 0, 
                "reservedRevocableBytes": 0, 
                "queryMemoryReservations": { }, 
                "queryMemoryRevocableReservations": { }, 
                "freeBytes": 10737418240
            }, 
            "general": {
                "maxBytes": 24696061952, 
                "reservedBytes": 0, 
                "reservedRevocableBytes": 0, 
                "queryMemoryReservations": { }, 
                "queryMemoryRevocableReservations": { }, 
                "freeBytes": 24696061952
            }, 
            "system": {
                "maxBytes": 16106127360, 
                "reservedBytes": 0, 
                "reservedRevocableBytes": 0, 
                "queryMemoryReservations": { }, 
                "queryMemoryRevocableReservations": { }, 
                "freeBytes": 16106127360
            }
        }
    }, 
    "processors": 40, 
    "processCpuLoad": 0.0004106776180698152, 
    "systemCpuLoad": 0.00041050903119868636, 
    "heapUsed": 9741942512, 
    "heapAvailable": 51539607552, 
    "nonHeapUsed": 264888168
}

 

内存限制和管理

单机维度

  • GENERAL_POOL每次内存申请时,都会判断内存使用量是否超过了最大内存,如果超过了就报错,错误为“Query exceeded local memory limit of x”,这保护了Presto会无限申请内存,只会导致当前查询出错。同时,如果该节点的GENERAL_POOL可使用内存以及可回收内存为0,那么认为该node为Block node。

  • RESERVED_POOL可以认为是查询最大的SQL,其能满足GENERAL_POOL的内存限制策略,那么肯定会满足RESERVED_POOL的策略(复用了GENERAL_POOL策略)。

  • RESERVED_POOL目前版本未发现可以限制内存,所以当并发非常高,且scan的数据非常大时,有低概率会引起OOM问题。但是配合Resource Group,内存设置合理,也基本会避免OOM问题。

集群维度

同时满足以下两点时,Presto便认为集群超出要求的内存了:

  • GENERAL_POOL出现阻塞节点(Block node)
  • RESERVED_POOL已经被使用

当判断出集群超出CLuster Memory时,有两种方式管理内存:
1、挨个遍历每个查询,判断当前查询占用的总内存是否超过了query.max-memory(config.properties里配置),如果超过了,那么该查询就被failed。
2、如果query.max-memory配置的不合理,值非常大,那么可能过了5秒(默认时间)依然不满足第一种情形,那么将会使用第二种方法管理查询。第二种管理方法又分为两种小的管理,根据LowMemoryKillerPolicy来决定Kill查询策略,其分为total-reservation和total-reservation-on-blocked-nodes。配置total-reservation的作用是kill掉所有查询里最费内存的查询;而total-reservation-on-blocked-nodes杀死在内存不足(阻塞)的节点上使用最多内存的查询。

转载于:https://my.oschina.net/u/2000675/blog/2086031

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值