Debugging Redis Connection Pool Blocking Issues in a Spring Backend Application
The article details a step‑by‑step investigation of a Spring‑based backend where API requests hung due to Redis connection pool misconfiguration, showing how thread dumps, jstack, and Arthas were used to pinpoint blocking in Jedis pool acquisition, and provides corrected configuration and proper connection handling recommendations.
The author, a senior architect, describes a week‑long outage in an internal sandbox where all APIs became unresponsive and the application appeared to be dead. Initial checks showed no errors in the database or Redis, leading to suspicion of the sandbox environment itself.
Using SSH, the author ran top and identified the most resource‑intensive threads with top -H -p 12798. A jstack of the process revealed several threads stuck in lock states, but no business‑level code was visible.
Further debugging involved remote debugging of the Tomcat process. After setting breakpoints at the AOP layer, the author discovered that the application hung while executing a Redis command. Inspection of the Jedis pool code showed that pool.getResource() eventually called internalPool.borrowObject(), which could block indefinitely when borrowMaxWaitMillis was negative.
The root cause was a missing maxWaitMillis configuration in the Redis pool, causing threads to wait forever for a connection. This was confirmed by thread dumps from Arthas showing many http-nio threads in a waiting state.
To fix the issue, the author added explicit pool configuration:
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxWaitMillis(2000);
... // other settings
jedisConnectionFactory.afterPropertiesSet();After restarting the service, the problem persisted until the pool timeout was correctly set, after which the API responses returned to normal.
The article also warns against using stringRedisTemplate.getConnectionFactory().getConnection() directly, recommending the use of
stringRedisTemplate.execute(new RedisCallback(){ public Cursor doInRedis(RedisConnection connection) throws DataAccessException { return connection.scan(options); } })or explicitly releasing connections with RedisConnectionUtils.releaseConnection(conn, factory). Additionally, it advises against using the KEYS command in production and stresses proper pool sizing.
In summary, the investigation demonstrates how thorough thread analysis, proper configuration of Redis connection pools, and correct usage of Spring's Redis utilities can prevent silent deadlocks and improve backend reliability.
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.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
