public <T> Flux<T> eval(
            RedisScript<T> script,
            short firstKey,
            byte[] secondKey,
            LongKeyGenerator keyGenerator) {
        int estimatedKeySize = Math.max(keyGenerator.estimatedSize(), 1);
        int clientSize = clients.size();
        long key;
        // fast path
        if (clientSize == 1) {
            key = keyGenerator.next();
            if (key == -1) {
                return Flux.empty();
            }
            ByteBuf keysBuffer = PooledByteBufAllocator.DEFAULT
                    // 8 for the size of argument metadata
                    .directBuffer((Short.BYTES + 8) + (secondKey.length + 8)
                            + estimatedKeySize * (Long.BYTES + 8));
            int keyCount = 2;
            try {
                CommandArgsUtil.writeRawShortArg(keysBuffer, firstKey);
                CommandArgsUtil.writeRawBytesArg(keysBuffer, secondKey);
                do {
                    keyCount++;
                    CommandArgsUtil.writeRawLongArg(keysBuffer, key);
                    key = keyGenerator.next();
                } while (key != -1);
            } catch (Exception e) {
                ReferenceCountUtil.safeEnsureReleased(keysBuffer);
                return Flux.error(e);
            }
            TurmsRedisClient client = clients.getFirst();
            Mono<T> eval = client.eval(script, keyCount, new CustomKeyBuffer(keysBuffer));
            return Flux.from(eval);
        }
        // slow path
        int keysPerClient = Math.max(estimatedKeySize / clientSize, 1);
        Map<TurmsRedisClient, BufferEntry> keyForClients = new IdentityHashMap<>(clientSize);
        while ((key = keyGenerator.next()) != -1) {
            TurmsRedisClient client = getClient(key);
            BufferEntry entry = keyForClients.get(client);
            ByteBuf buffer;
            if (entry == null) {
                buffer = PooledByteBufAllocator.DEFAULT.directBuffer((Short.BYTES + 8)
                        + (secondKey.length + 8) + keysPerClient * (Long.BYTES + 8));
                CommandArgsUtil.writeRawShortArg(buffer, firstKey);
                CommandArgsUtil.writeRawBytesArg(buffer, secondKey);
                entry = new BufferEntry(buffer, 2);
                keyForClients.put(client, entry);
            } else {
                buffer = entry.buffer;
                entry.incrementKeyCount();
            }
            CommandArgsUtil.writeRawLongArg(buffer, key);
        }
        int targetClientSize = keyForClients.size();
        if (targetClientSize == 0) {
            return Flux.empty();
        }
        List<Mono<T>> list = new ArrayList<>(targetClientSize);
        for (Map.Entry<TurmsRedisClient, BufferEntry> entry : keyForClients.entrySet()) {
            BufferEntry bufferEntry = entry.getValue();
            Mono<T> result = entry.getKey()
                    .eval(script, bufferEntry.keyCount, new CustomKeyBuffer(bufferEntry.buffer));
            list.add(result);
        }
        return Flux.merge(list);
    }
In fact, the method is designed for {@link UserStatusService#updateOnlineUsersTtl} currently

@param keyGenerator The size of keys should not be larger than 1,048,576(1024*1024), or Redis
                    will throw
turms-server-common/src/main/java/im/turms/server/common/storage/redis/TurmsRedisClientManager.java