Druid原理分析之内存池管理(转)

本文探讨了Druid如何通过对外内存和系统内存的使用来减轻JVM垃圾回收的性能影响,介绍了Druid中DirectBuffer的应用场景,以及如何通过固定分区内存池减少内存碎片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了减轻JVM垃圾回收带来的性能波动,Druid尽量使用对外内存和系统内存。

  • 使用临时文件,在索引创建和合并的过程中,中间临时结果会占用大量的内存。为了减少JVM内存的使用,采用临时文件,通过文件IO的方式,巧妙地利用内核的Page Cache。为了提升IO的性能,Linux操作系统增加了Page Cahe。文件IO的写操作会写到Page Cache中立即返回,内核会定时将脏页也就是还没写到磁盘的页刷到磁盘中,但是并不会立即删除Page Cache,以便读取时快速访问。Apache Kafka也正是利用了文件IO这种特性。
  • MMap在Java中通过调用ByteBuffer的get/put接口来实现文件的读写。他也是依赖于内核的Page Cache。他最大的优势是直接操作内核的内存,减少一次内存复制。
  • DirectBuffer,在Druid中DirectBuffer的使用场景如下:

1. 在索引创建的过程中按块压缩/编码,LZF压缩除外,默认块大小为64KB。

2. 在索引查询过程中按块解压缩/编码,存放解压缩以后的数据,默认块大小为64KB。

3. 在查询过程中存放中间结果集。

4. Group By查询在上下文中设置“userOffHeap=true”,则使用DirectBuffer存放计算结果集。

Druid采用固定分区的内存池。固定分区的优点是足够简单,缺点是每次申请分配固定大小的内存,容易造成内存碎片。但根据上述的使用场景,编码/解码,压缩/解压缩都是按块操作的,所以固定分区非常切合这种场景。Group By查询需要根据维度拉取原始数据,然后在内存中进行聚合操作。默认的内存增量索引使用JVM内存。为了减少创建大量临时对象,Druid设计了临时计算结果集,采用固定大小的对外内存存储Metric的值,先在临时计算结果集中聚合。Druid会给每个处理线程从内存池中申请一块内存,内存大小通过buffer.sizeBytes设置。Group By查询采用固定大小的内存,会造成内存浪费。处理线程每次只处理一个segment分片,为了兼顾处理较大的Segment分片,我们一般将内存块的大小设置的大一些。这样处理较小的segment分片就会造成内存浪费。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值