在多线程上下文中使用spring数据redis和莴苣的outofdirectmemoryerror

c9qzyr3d  于 2021-06-09  发布在  Redis
关注(0)|答案(1)|浏览(872)

我们正在使用 spring-data-redisspring-cache 抽象和 lettuce 作为我们的redis客户。另外,我们在一些方法上使用多线程和异步执行。
示例工作流如下所示:
主方法a(主线程)-->调用方法b( @Async )它是一个代理方法,可以在另一个线程中异步运行逻辑。-->方法b调用方法c,即 @Cacheable . 这个 @Cacheable 注解处理对redis缓存的读/写。
有什么问题吗? LettuceNetty -它依靠 DirectMemory . 由于 @Async 根据我们程序的性质,我们有多个线程使用 LettuceConnection (因此 Netty )同时。
根据设计,所有螺纹将使用相同的(?) Netty 它共享 DirectMemory . 因为明显太小了 MaxDirectMemorySize 我们得到一个 OutOfDirectMemoryError ,当太多线程正在访问 Netty .
例子: io.lettuce.core.RedisException: io.netty.handler.codec.EncoderException: io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 8388352 byte(s) of direct memory (used: 4746467, max: 10485760) 到目前为止我们发现了什么?
我们使用https://docs.cloudfoundry.org/buildpacks/java/ 然后计算 MaxDirectMemorySize 使用https://github.com/cloudfoundry/java-buildpack-memory-calculator.
哪一个利兹 MaxDirectMemorySize=10M . 具有4gb的实际可用内存 MaxDirectMemorySize 可能是保守的方式。这可能是问题的一部分。
问题的潜在解决方案
增加 MaxDirectMemorySize 但我们不确定这是否足够
配置 Netty 不使用 DirectMemory ( noPreferDirect=true ) --> Netty 然后将使用堆,但是如果这会使我们的应用程序速度过慢,那么我们是不安全的 Netty 对记忆来说太饥渴了
不知道这是否是一个选项,甚至使问题更糟:配置 LettuceshareNativeConnection=false -->这将导致多个连接到redis
我们的问题是:我们如何以正确的方式解决这个问题?
我很乐意提供更多关于如何设置应用程序配置(application.yml、lettuceconnection等)的信息,如果其中任何一个有助于解决问题的话。

svujldwt

svujldwt1#

感谢大家:https://gitter.im/lettuce-io/lobby 我们找到了一些解决这些问题的线索。
正如怀疑的那样 MaxDirectMemorySize 考虑到总的可用内存太保守了。
建议增加这个值。因为我们不知道有多少记忆 Netty 要想表现得更稳定,我们考虑了以下步骤。
第一:我们将禁用 Netty 的首选项 MaxDirectMemory 通过设置 noPreferDirect=true . Netty 然后将使用堆缓冲区。
第二:我们将监视堆内存的大小 Netty 在操作过程中消耗。这样,我们就可以推断出 Netty .
第三:我们将取平均内存消耗值并将其设置为“new” MaxDirectMemorySize 通过在jvm选项中设置它 -XX:MaxDirectMemorySize . 那我们就启用了 Netty 使用 DirectMemory 通过设置 noPreferDirect=false .
第四:监视日志条目和异常,看看我们是否仍然有问题,或者这是否起到了作用。
[更新]我们从上述步骤开始,但意识到 noPreferDirect=true 不会完全阻止netty使用directmemory。对于某些用例(nio过程) Netty 仍然使用directmemory。
所以我们必须增加 MaxDirectMemorySize .
现在,我们设置以下java\u选项 -Dio.netty.noPreferDirect=true -XX:MaxDirectMemorySize=100M . 这可能会解决我们的问题。

相关问题