当前位置:网站首页 > R语言数据分析 > 正文

webflux使用堆外内存(webflux databuffer)



简介:
通过对推荐权益业务的缓存改造,对比分析在本地缓存数据量较大的背景下,分别使用堆内内存与堆外内存实现缓存策略的接口性能表现。探索开源高性能缓存库OHC在推荐权益业务的适用性。

业务背景:

在会员权益推荐中,我们把推荐的权益信息放入本地缓存,通过Caffeine进行管理。随着权益数据及推荐渠道、运营位置的增多,推荐权益的基础配置量也快速累积。我们知道,本地缓存占用JVM内存,数据量过多会影响GC,造成GC频率、耗时增加,进而对系统性能产生直接影响。那么在本地缓存数据量多的情况下有没有其他解决方案呢?

优势:

使用堆外缓存OHC(Off-Heap Cache)的优势:

    · 不占用JVM堆内存,摆脱GC影响
    · 支持异步缓存加载机制
    · 支持为每个缓存条目单独设置或使用默认的TTL(Time-To-Live,生存时间)/过期时间
    · 能够在不需要额外线程的情况下进行缓存条目的淘汰和过期处理
    · 具备管理大规模缓存内存的能力
    · 通过分块实现方式,适合存储低开销的极小或小型缓存条目




实现过程:

一 接入OHC并序列化

OHC快速接入示例中,需要我们自定义序列化方式,Protobuf、Thrift、kryo、hessian自由选择。以下示例采用Protobuf序列化。

1) 引入POM依赖: 

2) 构建堆外权益缓存:

二 实践及效果

  1. 数据准备:

首先看看本地配置JVM启动的几个关键指标:

-Xmx1g: -Xms1g设置JVM初始堆内存最大堆内存为1GB。

-XX : +UseConcMarkSweepGC: 启用CMS垃圾回收器。

-XX : CMSInitiatingOccupancyFraction=70: 设置堆内存使用率达到70%时触发CMS垃圾回收

-XX : MaxDirectMemorySize 最大堆外内存

根据参数配置,我们可模拟构建10w+个权益对象,使权益内存到达700M(可以使用jol查询某个对象总共占用了多少内存空间),以此来触发CMS工作。

注:压测工具及数据均一致,使用Jmeter压测权益推荐接口,30s内10个线程持续请求。

  1. 内存及GC状态对比:

将本地内存切换为堆外内存后,为了更直观的对比两者的GC状态及接口性能,我们分别监控不使用缓存场景、使用堆内内存场景、使用堆外内存三组场景下的GC静息状态及压测状态下,heap内存和gc状态变化(GC次数及GC时长)。并输出压测报告。

· 无缓存

 

                                          图 I无缓存内存图                               

                                                                     图 II无缓存GC状态

项目启动时,基础类加载使用250M内存,GC再类加载时开始工作,FULL GC 0次,Minor GC 29次,每次约10ms。

· 使用堆内内存

  

                                                                图 III 堆内存静息时内存

                                                                 图 IV 堆内存静息时GC

项目启动即开始加载权益缓存,内存使用750M开始触发GC工作,其中FULL GC50次,每次28ms,Minor GC 32次,每次11.5ms

                                                                图 V 堆内存压测时GC

项目压测时,可以看到GC开始加速工作,FULL GC次数达184次,每次耗时增加到88ms。

                                                                图 VI 堆内存压测报告

·使用OHC堆外内存

  

                                                        图 VII 堆外静息状态内存

                                                        图 VIII 堆外内存静息状态GC

项目启动堆内内存无变化,GC基本跟无缓存使用状态一致。

                                                        图 IX 堆外内存压测时GC

项目压测时,可以看到GC开始工作,FULL GC次数0次,Minor约6ms。

                                                        图 X 堆外内存压测报告

  1. 现象分析:

将本地缓存的大对象,移出到堆外缓存后,GC减少,接口性能提升2.2倍

三 源码浅析

1)内存分配

点开put方法,发现核心OHCache接口提供了两种实现:

OHCacheLinkedImpl: 实现为每个条目单独分配堆外内存,最适合中型和大型条目。

OHCacheChunkedImpl:实现为每个散列段作为一个整体分配堆外内存,并且适用于小条目。(实验性的,不做关注)

OHCacheLinkedImpl的主要工作流程如下:

·计算key的hash值,根据hash值计算段号,确定其所处的OffHeapLinkedMap

·从OffHeapLinkedMap中获取该键值对的堆外内存地址(指针)

·对于get操作,从指针所指向的堆外内存读取byte[],把byte[]反序列化成对象

·对于put操作,把对象序列化成byte[],并写入指针所指向的堆外内存

2)内存释放

释放内存对应也有两种方法,一个用的是sun.misc.Unsafe的freeMemory,一个用的是com.sun.jna.Native的free,可以肯定的是,都需要我们手动释放。如果写C可能觉得这是天经地义的,毕竟你向操作系统借了一块内存,那肯定要还的。但是还内存这一步,Java程序员平时都是全权交由JVM管理的。

四 缓存使用建议

1)当本地缓存对垃圾回收(GC)造成显著影响时,可以采用堆外缓存(OHC)来降低其对GC的负担;

2))由于OHC将键(key)和值(value)序列化为字节数组后存储在堆外内存中,因此选择一个高效的序列化工具对于优化性能至关重要;

3) 为了减少缓存对象的体积,可以缩短缓存的JSON字符串中的字段名,这不仅减少了数据存储和传输量,还有助于增强数据的隐私性;

4)OHC可替代Caffeine等堆内存中间件的主要特性,至于你的项目是否需要使用堆外内存,还要取决于你的堆内内存占用量是否对GC产生了影响。

五 结果及影响

高效利用服务器内存,对本地需缓存较大数据量的业务场景提供新的解决方案。当本地缓存对垃圾回收(GC)造成显著影响时,可以采用堆外缓存来降低GC负担。如上文所示,堆内内存达到GC触发阈值的条件时,将堆内内存移出至堆外,推荐权益的接口性能提升了2.2倍;

到此这篇webflux使用堆外内存(webflux databuffer)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • tornami a vagheggiar翻译(tornadoes翻译)2025-07-30 14:18:06
  • orexis怎么读(orchids怎么读)2025-07-30 14:18:06
  • chrony查看同步情况(chrony不同步)2025-07-30 14:18:06
  • 双系统直接删除linux开不了机(双系统直接删除linux导致出现grub)2025-07-30 14:18:06
  • 投屏airplay是什么设备(airplayer投屏)2025-07-30 14:18:06
  • display:grid 兼容性(displaylink不兼容)2025-07-30 14:18:06
  • rpro怎么读(roper怎么读)2025-07-30 14:18:06
  • rise是什么意思(sell是什么意思)2025-07-30 14:18:06
  • cruise是干嘛的(cruise是什么意思英语)2025-07-30 14:18:06
  • strip工具(srtr工具箱)2025-07-30 14:18:06
  • 全屏图片