Optimizing with Pipelining
1. Understanding Pipeline Concept
| Concept | Detail |
| Batching | Send many commands without waiting per-reply |
| Goal | Eliminate RTT cost for bulk ops |
| Atomicity | NOT atomic — use MULTI for atomicity |
2. Implementing Pipeline in Clients
Example: Pipeline in Jedis
try (Pipeline p = jedis.pipelined()) {
for (int i = 0; i < 1000; i++) p.set("k:" + i, "v");
List<Object> results = p.syncAndReturnAll();
}
3. Batching Multiple Commands
| Batch Size | Throughput Impact |
| 1 | Baseline |
| 100 | ~30-50× faster |
| 1000 | ~50-100× faster (LAN) |
4. Handling Pipeline Responses
| API | Behavior |
pipe.sync() | Flush and discard replies |
pipe.syncAndReturnAll() | Flush and collect ordered replies |
Response<T> | Per-command future |
5. Comparing Pipelining vs Transactions
Pipeline
- Performance optimization
- Not atomic
- Other clients interleave
- Any commands allowed
Transaction (MULTI/EXEC)
- Atomic execution
- Server queues all commands
- WATCH for CAS
- No interleaving
6. Understanding Round-Trip Time Savings
| RTT | 10K ops sequential | 10K ops pipelined (batch 100) |
| 0.5 ms | 5 s | ~50 ms |
| 10 ms (WAN) | 100 s | ~1 s |
redis-benchmark -t set -n 100000 -P 100 # pipelined
redis-benchmark -t set -n 100000 # no pipeline
| Flag | Effect |
-P n | Pipeline batch size |
8. Using Pipeline with Lua Scripts
| Pattern | Benefit |
| Pipeline of EVALSHA | Combines atomic op + batching |
9. Managing Pipeline Buffer Size
Warning: Huge pipelines can exhaust client/server memory. Keep batches under 10K commands.
| Setting | Purpose |
client-output-buffer-limit normal | Server-side buffer cap per client |
| Client send buffer | Flush in chunks to bound memory |
10. Avoiding Pipeline Pitfalls
| Pitfall | Avoid By |
| Cross-slot pipelines in Cluster | Split by slot, use hashtags {tag} |
| Mixing blocking ops | Don't pipeline BLPOP/BRPOP |
| Out-of-order assumption | Replies match command order |