Databases 27 min read

Analysis of Redis Pipeline Support in Spring Boot with Lettuce and Redisson Clients

The article examines how Spring Boot’s Lettuce and Redisson clients implement Redis pipelining, explains the batch‑request principle, benchmarks 100 000 set inserts showing pipeline speeds of 0.5–1.4 seconds versus 162 seconds for single commands, demonstrates Spring Data Redis callback usage, warns of high‑cost command pitfalls, and details Redisson’s RBatch internals, concluding that pipelining dramatically boosts throughput when command costs are modest.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Analysis of Redis Pipeline Support in Spring Boot with Lettuce and Redisson Clients

Redis is a client‑server TCP service that supports pipelining to improve batch command performance. This article analyzes how the Lettuce and Redisson clients in a Spring Boot environment implement the Redis Pipeline feature, explains the underlying principles, and presents practical performance comparisons.

Pipeline principle : By sending multiple commands in a single request and receiving all replies together, the number of round‑trip times (RTT) and the number of system calls (read/write) are reduced, which greatly improves throughput.

Typical single‑command flow: client sends a request, blocks waiting for a response, server processes the command and returns the result. With pipelining, multiple commands are buffered on the client side, sent together, and the server processes them sequentially, returning a batch of results.

Performance test : Inserting 100 000 set entries was measured using three approaches:

@Slf4j
public class RedisPipelineTestDemo {
    public static void main(String[] args) {
        // connect redis
        Jedis jedis = new Jedis("10.101.17.180", 6379);
        String zSetKey = "Pipeline-test-set";
        int size = 100000;

        long begin = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            jedis.sadd(zSetKey + i, "aaa");
        }
        log.info("Jedis single insert time: {}ms", (System.currentTimeMillis() - begin));

        // Jedis Pipeline
        Pipeline pipeline = jedis.pipelined();
        begin = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            pipeline.sadd(zSetKey + i, "bbb");
        }
        pipeline.sync();
        log.info("Jedis Pipeline time: {}ms", (System.currentTimeMillis() - begin));

        // Redisson Pipeline (RBatch)
        Config config = new Config();
        config.useSingleServer().setAddress("redis://10.101.17.180:6379");
        RedissonClient redisson = Redisson.create(config);
        RBatch redisBatch = redisson.createBatch();
        begin = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            redisBatch.getSet(zSetKey + i).addAsync("ccc");
        }
        redisBatch.execute();
        log.info("Redisson Pipeline time: {}ms", (System.currentTimeMillis() - begin));

        // close resources
        pipeline.close();
        jedis.close();
        redisson.shutdown();
    }
}

Results:

Jedis single insert time: 162655ms
Jedis Pipeline time: 504ms
Redisson Pipeline time: 1399ms

The pipeline modes dramatically outperform single command execution.

Spring Boot usage : Spring Data Redis provides StringRedisTemplate.executePipelined with two callback types— RedisCallback and SessionCallback . Example implementations for inserting a batch of set entries are shown below.

public void testRedisCallback() {
    List
ids = Arrays.asList(1,2,3,4,5,6,7,8,9);
    Integer contentId = 1;
    redisTemplate.executePipelined(new InsertPipelineExecutionA(ids, contentId));
}
@AllArgsConstructor
private static class InsertPipelineExecutionA implements RedisCallback
{
    private final List
ids;
    private final Integer contentId;
    @Override
    public Void doInRedis(RedisConnection connection) {
        RedisSetCommands redisSetCommands = connection.setCommands();
        ids.forEach(id -> {
            String redisKey = "aaa:" + id;
            String value = String.valueOf(contentId);
            redisSetCommands.sAdd(redisKey.getBytes(), value.getBytes());
        });
        return null;
    }
}
public void testSessionCallback() {
    List
ids = Arrays.asList(1,2,3,4,5,6,7,8,9);
    Integer contentId = 1;
    redisTemplate.executePipelined(new InsertPipelineExecutionB(ids, contentId));
}
@AllArgsConstructor
private static class InsertPipelineExecutionB implements SessionCallback
{
    private final List
ids;
    private final Integer contentId;
    @Override
    public Void execute(RedisOperations
operations) {
        SetOperations
setOps = (SetOperations
) operations.opsForSet();
        ids.forEach(id -> setOps.add("aaa:" + id, String.valueOf(contentId)));
        return null;
    }
}

Pitfalls : Using pipeline for commands with high per‑command cost (e.g., lrem on large lists) can still cause CPU and memory spikes. Switching to ltrim , which has O(M) complexity, resolves the issue.

Redisson implementation : Redisson’s pipeline is realized through the RBatch interface. Commands are queued in a BatchCommandData list and sent in a single Netty write operation. The execution flow involves CommandBatchService , RedisBatchExecutor , and finally RedisConnection.send . The result handling aggregates individual command results into a BatchResult .

public class RedisPipelineTest {
    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://xx.xx.xx.xx:6379");
        RedissonClient redisson = Redisson.create(config);
        RBatch redisBatch = redisson.createBatch();
        int size = 100000;
        String zSetKey = "Pipeline-test-set";
        long begin = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            redisBatch.getSet(zSetKey + i).addAsync("ccc");
        }
        redisBatch.execute();
        log.info("Redisson Pipeline time: {}ms", (System.currentTimeMillis() - begin));
        redisson.shutdown();
    }
}

Conclusion : Redis pipelining can significantly improve performance for batch operations, but developers must consider the cost of each command. The article compares Lettuce and Redisson implementations, providing insight into how different Java Redis clients realize pipeline support.

JavaperformanceRedisSpring BootpipelineRedissonLettuce
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.