Why Redis Increment Returns Null with @Transactional and How to Fix It
A production microservice failed each morning because Redis's increment operation returned null when generating IDs, and restarting the service temporarily fixed it; the article investigates the root cause—Redis transaction support combined with Spring @Transactional—and presents two concrete remediation strategies.
Problem
In a production environment, creating a customer‑service event each morning failed because the Redis increment used to generate a distributed ID returned null. Restarting the microservice restored normal behavior for that day.
Initial Investigation
The increment is performed via redisTemplate.opsForValue().increment("count", 1). The method returned null only in the early‑morning runs.
Hypotheses
Large number of Redis connections left open overnight, causing the increment to fail.
Redis pipeline or transaction usage causing a null return.
Interaction between Spring's @Transactional annotation and Redis operations.
Verification
Hypothesis 1 was discarded because other Redis‑using features worked correctly.
Redis documentation states that increment returns null when executed inside a pipeline or a transaction. The service implementation was examined and found a @Transactional annotation on the method, suggesting a possible link.
A demo project was built to compare results with and without @Transactional. When the method lacked the annotation, the increment returned the expected value; with the annotation it still returned a value, indicating the annotation alone was not the cause.
Further experiments enabled Redis transaction support (via setEnableTransactionSupport) and executed the increment inside a Spring @Transactional method. In this configuration the increment consistently returned null, reproducing the production symptom.
Root Cause
When StringRedisTemplate is configured with transaction support, any Redis command executed inside a Spring @Transactional method is treated as part of a Redis transaction. The command is queued, and the method receives null until the transaction is committed, after which the actual increment occurs.
Fixes
Two remediation approaches were considered:
After each Redis transaction, disable transaction support before executing ordinary Redis commands. This approach has a drawback: if a @Transactional method runs while a transaction is active, the problem reappears.
Define two separate StringRedisTemplate beans: one with transaction support for transactional operations and one without for normal commands. Use the appropriate bean in each context.
The second solution was implemented. A RedisConfig class declares stringRedisTemplate (no transaction) and stringRedisTemplateTransaction (transaction enabled). Services were updated to inject the correct bean, and tests confirmed that the increment now returns the expected count, resolving the issue.
Conclusion
Enabling Redis transaction support together with Spring's @Transactional causes the Redis increment operation to return null because the command is queued in a Redis transaction. Using separate RedisTemplate instances or disabling transaction support for non‑transactional operations eliminates the problem.
return redisTemplate.opsForValue().increment("count", 1); stringRedisTemplate.opsForValue().increment("count", 1);Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
