How to reduce memory footprint of RedisClient
QuChen88 opened this issue · 1 comments
Current Behavior
We noticed that each lettuce client uses ~4 MB of memory even when we are not issuing large commands that are several MBs in size to Redis. I would expect ~KBs of memory usage in our case.
I did a heap dump analysis and observed those byte[]
buffers are allocated from io.lettuce.core.protocol.CommandHandler
and io.lettuce.core.protocol.RedisStateMachine

Input Code
Input Code
ClientResources resources = ClientResources.builder().nettyCustomizer(new NettyCustomizer() {
@Override
public void afterBootstrapInitialized(Bootstrap bootstrap) {
String dbInterfaceName = System.getProperty(SystemSetting.DB_INTERFACE_NAME.getName(), null);
try {
if (dbInterfaceName == null) {
bootstrap.localAddress(new InetSocketAddress("0.0.0.0", 0)); // <- This is the case for me
} else {
NetworkInterface networkInterface = NetworkInterface.getByName(dbInterfaceName);
InetAddress inetAddress = networkInterface.getInetAddresses().nextElement();
bootstrap.localAddress(new InetSocketAddress(inetAddress, 0));
}
} catch (SocketException e) {
throw new RuntimeException("Unable to lookup IP address for interface '" + dbInterfaceName + "'", e);
}
}
}).eventExecutorGroup(eventLoopGroup).build();
final RedisURI redisUriCluster =
RedisURI.Builder.redis(endpoint).withPort(port).withSsl(true).withVerifyPeer(false).build();
RedisClient redisClient = RedisClient.create(resources, redisUriCluster);
ClientOptions options = ClientOptions.builder()
.socketOptions(SocketOptions.builder()
.keepAlive(true)
.connectTimeout(CONNECTION_TIMEOUT_MILLIS)
.build())
.disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
.autoReconnect(true)
.timeoutOptions(TimeoutOptions.builder()
.fixedTimeout(FIXED_TIMEOUT_MILLIS)
.build())
.build();
redisClient.setOptions(options);
Expected behavior/code
Is this expected behavior? If so, are there ways for me to reduce the memory footprint of lettuce clients?
We are running on a relatively memory constraint system with only ~1GB of memory. We configured about 570MB of direct memory. (i.e. JVM config parameter -Xms256m -Xmx640m -XX:MaxDirectMemorySize=570m -DdirectMemorySoftLimit=320m
). We can support more lettuce client connections if the memory footprint can be lowered here.
Environment
- Lettuce version(s): 6.2.5 RELEASE
- Redis version: 7.0
This is by design. Lettuce is intended for advanced high-performance usage where we have several pre-initialized buffers to be used for sending and receiving commands. The event-based design requires a different approach than an InputStream
-based client that just reads and writes protocol bytes.
If you have to limit memory to 1GB, then you might be better off just using Jedis.