Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to reduce memory footprint of RedisClient #2915

Open
QuChen88 opened this issue Jul 10, 2024 · 1 comment
Open

How to reduce memory footprint of RedisClient #2915

QuChen88 opened this issue Jul 10, 2024 · 1 comment

Comments

@QuChen88
Copy link

QuChen88 commented Jul 10, 2024

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

Screenshot 2024-07-10 at 11 54 35 AM

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
@mp911de
Copy link
Collaborator

mp911de commented Jul 26, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants