All Products
Search
Document Center

ApsaraDB for Redis:JedisPool optimization

Last Updated:Feb 19, 2024

JedisPool is a connection pool for the Jedis client. You can appropriately configure JedisPool parameters to improve the performance and resource usage of Redis. This topic describes how to use JedisPool and its resource pool parameters, and provides the recommended settings to optimize JedisPool.

Use JedisPool

Jedis 2.9.0 is used in this example. The following sample code shows the Maven dependency:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <scope>compile</scope>
</dependency>

Jedis manages the resource pool by using Apache Commons-pool2. When you define JedisPool, we recommend that you pay attention to the GenericObjectPoolConfig parameter of the resource pool. The following sample code shows how to use this parameter:

GenericObjectPoolConfig jedisPoolConfig = new GenericObjectPoolConfig();
jedisPoolConfig.setMaxTotal(...);
jedisPoolConfig.setMaxIdle(...);
jedisPoolConfig.setMinIdle(...);
jedisPoolConfig.setMaxWaitMillis(...);
...

The following example shows how to initialize JedisPool:

redisHost specifies the IP address of the instance. redisPort specifies the port of the instance. redisPassword specifies the password of the instance. The timeout parameter specifies the connection timeout and the read/write timeout. 
JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPassword);
// Run the following commands: 
Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    // Specific commands 
    jedis.executeCommand()
} catch (Exception e) {
    logger.error(e.getMessage(), e);
} finally {
    //In JedisPool mode, the Jedis resource is returned to the resource pool. 
    if (jedis != null) 
        jedis.close();
}

Parameters

The Jedis connection is a resource managed by JedisPool in the connection pool. JedisPool is a thread-safe pool of connections. It allows you to keep all resources within a manageable range. If you set the GenericObjectPoolConfig parameter to a proper value, you can improve the performance of Redis and reduce resource consumption. The following two tables describe important parameters and provide the recommended settings.

Table 1. Parameters related to resource settings and resource usage

Parameter

Description

Default value

Recommended settings

maxTotal

The maximum number of connections in the pool.

8

For more information, see Recommended settings.

maxIdle

The maximum number of idle connections in the pool.

8

For more information, see Recommended settings.

minIdle

The minimum number of idle connections in the pool.

0

For more information, see Recommended settings.

blockWhenExhausted

Specifies whether the client must wait when the resource pool is exhausted. Only when this parameter is set to true, the maxWaitMillis parameter takes effect.

true

We recommend that you use the default value.

maxWaitMillis

The maximum number of milliseconds that the client must wait when no connection is available.

-1 (indicates that the connection never times out.)

We recommend that you do not use the default value.

testOnBorrow

Specifies whether to validate connections by using the PING command before the connections are borrowed from the pool. Invalid connections are removed from the pool.

false

We recommend that you set this parameter to false when the workload is heavy. This allows you to reduce the overhead of a ping test.

testOnReturn

Specifies whether to validate connections by using the PING command before the connections are returned to the pool. Invalid connections are removed from the pool.

false

We recommend that you set this parameter to false when the workload is heavy. This allows you to reduce the overhead of a ping test.

jmxEnabled

Specifies whether to enable Java Management Extensions (JMX) monitoring.

true

We recommend that you enable JMX monitoring. Take note that you must also enable the feature for your application.

The detection of idle Jedis objects is controlled by a combination of four parameters.

Table 2. Parameters related to idle resource detection

Parameter

Description

Default value

Recommended settings

testWhileIdle

Specifies whether to validate connections by running the PING command during the process of idle resource monitoring. Invalid connections are evicted.

false

true

timeBetweenEvictionRunsMillis

The cycle of idle resource detection. Unit: milliseconds.

-1 (indicates that idle resource detection is disabled.)

We recommend that you set this parameter to a proper value. You can also use the default configuration in JedisPoolConfig.

minEvictableIdleTimeMillis

The minimum idle time of a resource in the resource pool. Unit: milliseconds. When the upper limit is reached, the idle resource is evicted.

1,800,000 (30 minutes)

The default value is suitable for most cases. You can also use the configuration in JeidsPoolConfig based on your business requirements.

numTestsPerEvictionRun

The number of resources to be detected within each cycle.

3

You can change the value based on your application connections. A value of -1 specifies that the system checks all connections for idle resources.

Jedis provides JedisPoolConfig that uses some configurations of GenericObjectPoolConfig for idle resource detection.

public class JedisPoolConfig extends GenericObjectPoolConfig {
  public JedisPoolConfig() {
    setTestWhileIdle(true);
    setMinEvictableIdleTimeMillis(60000);
    setTimeBetweenEvictionRunsMillis(30000);
    setNumTestsPerEvictionRun(-1);
    }
}
Note

You can view all default values in org.apache.commons.pool2.impl.BaseObjectPoolConfig.

Recommended settings

maxTotal: The maximum number of connections.

To set a proper value for maxTotal, take note of the following factors:

  • The expected concurrent connections based on your business requirements.

  • The amount of time that is consumed by the client to run the command.

  • The limit of Redis resources. For example, if you multiply the value of maxTotal by the number of nodes (ECS instances), the resulting value must be smaller than the maximum number of connections supported by Redis. You can view the maximum number of connections on the Instance Information page in the ApsaraDB for Redis console.

  • The amount of resources that are consumed to create and release connections. If the number of connections that are created and released for a request is large, the processes that are run to create and release connections are adversely affected.

For example, the average time that is consumed to run a command, or the average time that is required to borrow or return resources and to run Jedis commands with network overhead, is approximately 1 ms. The queries per second (QPS) of a connection is about 1,000, which is calculated by dividing 1 second by 1 millisecond. The expected QPS of an individual Redis instance is 50,000 (the total number of QPS divided by the number of Redis shards). The theoretically required size of a resource pool (maxTotal) is 50, which is calculated by dividing 50,000 by 1,000.

However, this is only a theoretical value. It is also essential to reserve some extra resources to account for unpredicted demands. Therefore, we recommend that you set maxTotal to a value larger than the calculated estimate. However, if the value of the maxTotal parameter is excessively large, the connections consume a large amount of client and server resources. For Redis servers that have a high QPS, if a large number of commands are blocked, the issue cannot be resolved even by a large resource pool.

maxIdle and minIdle

maxIdle indicates the actual maximum number of connections required by workloads. maxTotal includes the number of idle connections as a surplus. If the value of maxIdle is small on heavily loaded systems, new Jedis connections are created to serve the requests. minIdle indicates the minimum number of established connections that must be kept in the pool.

The connection pool achieves its best performance when the maxTotal value is equal to the maxIdle value. This way, the performance is not affected by the scaling of the connection pool. We recommend that you set the maxIdle and minIdle parameters to the same value if the user traffic fluctuates. If the number of concurrent connections is small or if the value of maxIdle is excessively large, the connection resources are wasted.

You can evaluate the size of the connection pool used by each node based on the actual total QPS and the number of clients that Redis serves.

Retrieve proper values based on monitoring data

In actual scenarios, a more reliable method is to try to retrieve optimal values based on monitoring data. You can use JMX monitoring or other monitoring tools to find proper values.

FAQ

Resources are insufficient.

You cannot obtain resources from the resource pool in the following cases:

  • Timeout:

    redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    ...
    Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)
  • When you set the blockWhenExhausted parameter to false, the time specified by borrowMaxWaitMillis is not used and the borrowObject call blocks the connection until an idle connection is available.

    redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    ...
    Caused by: java.util.NoSuchElementException: Pool exhausted
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

This exception may not be caused by a limited pool size. For more information, see Recommended settings. To fix this issue, we recommend that you check the network, the parameters of the resource pool, the resource pool monitoring (JMX monitoring) service, the code (for example, the reason is that jedis.close() is not executed), slow queries, and the Domain Name System (DNS).

Preload JedisPool

If you specify a small timeout value, the project may time out after it is started. JedisPool does not create a Jedis connection in the connection pool when JedisPool defines the maximum number of resources and the minimum number of idle resources. If no idle connection exists in the pool, a new Jedis connection is created. This connection is released to the pool after the connection is used. However, the process in which you create a connection and repeatedly release the connection may take a long period of time. Therefore, we recommend that you preload JedisPool with the minimum number of idle connections after JedisPool is defined. The following example shows how to preload JedisPool:

List<Jedis> minIdleJedisList = new ArrayList<Jedis>(jedisPoolConfig.getMinIdle());

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = pool.getResource();
        minIdleJedisList.add(jedis);
        jedis.ping();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
    }
}

for (int i = 0; i < jedisPoolConfig.getMinIdle(); i++) {
    Jedis jedis = null;
    try {
        jedis = minIdleJedisList.get(i);
        jedis.close();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    } finally {
    
    }
}

For information about other errors, see Common errors and troubleshooting.