Spring Session with Redis - keys are not getting expired in Redis - spring

I am new to spring-data-redis. I have integrated with a spring-boot application. As part of this, I have added a few configs as follows:
spring.session.store-type=redis
spring.session.redis.namespace=tc
server.servlet.session.timeout=5h
But even after having the expiry timeout as 5 hrs, I see all records which are months old, in redis:
127.0.0.1:6379> keys *
1) "tc:expirations:1653887100000"
2) "tc:sessions:2a4d193c-612b-48b6-8b7a-3ac525aba2d4"
3) "tc:sessions:fd10e891-357a-4cd4-a14b-58a1bb2e16ae"
4) "tc:sessions:expires:99969082-b0bc-4122-9511-1aba098a0eb7"
5) "tc:sessions:expires:b9a84856-9971-4e9e-bfec-9037ceb7d317"
6) "tc:expirations:1653897300000"
7) "tc:sessions:expires:b8c9969c-6bde-4aca-8d2e-7510d90f9706"
8) "tc:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:abcd"
In this context, I have gone through: Spring Session with Redis - server.session.timeout has no effect and I see I have done exactly the same as the accepted answer suggested. So I am not sure, what I am missing here.

Here's a configuration i've done on my project with Spring session and Redis
The timeout should be set on spring session parameters
*Sorry for the yaml... :) *
spring:
redis:
host: localhost
port: 6379
session:
store-type: redis
timeout: 3000
redis:
namespace: spring:session
flush-mode: on_save

If you are using the #EnableRedisHttpSession annotation you need to set maxInactiveIntervalInSeconds like:
#EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400)

Related

Difference between spring.session.timeout property and <session-timeout> tag in web.xml

Trying to store my HttpSession using Redis in Spring Boot. All guides mention session timeout properties - like spring.session.timeout - and previously I used to define timeout in web.xml. Can't figure\find out the difference between those two.
When I comment out timeout in web.xml and use property - for example 1 minute timeout - it is not being 1 minute after deploy. Are those two ways connected somehow? Or those are completely different things?
UPD 1: Also I am using #EnableRedisHttpSession with no args, if that affects it

Spring Boot cannot config database connection down to zero

I am deploying my Spring Boot REST API on AWS Fargate, which connects to AWS Aurora Postgresql Serverless V1.
I have configured the Aurora to scale the ACU to 0 when idle as in the following picture, so that I am not charge too much when I don't use the API.
Initially, my Spring Boot App maintains 10 idle connections by default, so I have tried to make it zero by adding the this to application.properties
spring.datasource.minimumIdle=0
And then I see from AWS console that the database connection has been reduced. But it remains 1 connection forever.
Please help suggest if you know how to make it zero.
The Spring Boot database configuration is basically like this
#Bean
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Edit 1
I used the suggestion in the comment to check if the connection really comes from Spring Boot.
It turns out there is no active connection but /actuator/metrics/hikaricp.connections.idle always return the value of 1
{"name":"hikaricp.connections.idle","description":"Idle connections","baseUnit":null,"measurements":[{"statistic":"VALUE","value":1.0}],"availableTags":[{"tag":"pool","values":["HikariPool-1"]}]}
And it seems does not relate to health check because I have tried running it locally and the result of /actuator/metrics/hikaricp.connections.idle remains 1.
I set logging.level.root = trace to see what is happening.
There are only 2 things keep printing in the log periodically
The Hikari connection report, showing 1 idle connection
{"level":"DEBUG","ref":"|","marker":"INTERNAL","message":"HikariPool-1 - Before cleanup stats (total=1, active=0, idle=1, waiting=0)","logger":"com.zaxxer.hikari.pool.HikariPool","timestamp":"2022-06-14 16:15:16.799","thread":"HikariPool-1 housekeeper"}
{"level":"DEBUG","ref":"|","marker":"INTERNAL","message":"HikariPool-1 - After cleanup stats (total=1, active=0, idle=1, waiting=0)","logger":"com.zaxxer.hikari.pool.HikariPool","timestamp":"2022-06-14 16:15:16.800","thread":"HikariPool-1 housekeeper"}
{"level":"DEBUG","ref":"|","marker":"INTERNAL","message":"HikariPool-1 - Fill pool skipped, pool is at sufficient level.","logger":"com.zaxxer.hikari.pool.HikariPool","timestamp":"2022-06-14 16:15:16.800","thread":"HikariPool-1 housekeeper"}
Tomcat NioEndpoint, but I think it is not relevant
{"level":"DEBUG","ref":"|","marker":"INTERNAL","message":"timeout completed: keys processed=0; now=1655198117181; nextExpiration=1655198117180; keyCount=0; hasEvents=false; eval=false","logger":"org.apache.tomcat.util.net.NioEndpoint","timestamp":"2022-06-14 16:15:17.181","thread":"http-nio-8445-Poller"}
Thanks to the suggestion in the comment, this is because of the actuator health check, which can be solved by the following settings
management.health.db.enabled=false

When using spring-boot-starter-data-redis, how to set the eviction policy? LFU or LRU etc?

When redis is used as a caching technology through spring boot (<artifactId>spring-boot-starter-data-redis</artifactId>), i see few properties like TTL can be set in the application.properties file.
ex:
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=600000
and few more snippets from - Appendix A. Common application properties
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.url= # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password#example.com:6379
spring.redis.host=localhost # Redis server host.
But I am not able to figure out how to set the cache eviction policy like - Least Frequently Used or Last Recently Used etc.
How and where do I have to provide this config details ??
Redis cache documentation states:
It is possible to set the configuration directive using the redis.conf
file, or later using the CONFIG SET command at runtime.
Redis configuration documentation states:
maxmemory 2mb
maxmemory-policy allkeys-lru
Combining the two, the command to change the eviction policy is:
CONFIG SET maxmemory-policy allkeys-lfu
Using Spring Data Redis:
If using non-reactive Redis connection:
RedisConnection conn = null;
try {
conn = connectionFactory.getConnection();
conn.setConfig("maxmemory-policy", "allkeys-lfu");
} finally {
if (conn != null) {
conn.close();
}
}
If using reactive Redis connection:
ReactiveRedisConnection conn = connectionFactory.getReactiveConnection();
conn
.serverCommands()
.setConfig("maxmemory-policy", "allkeys-lfu")
.filter(status -> status.equals("OK"))
.doFinally(unused -> conn.close())
.block(Duration.ofSeconds(5L));

Does jdbc template closes connections in case of inactivity

In my Spring Boot microservice I have autoconfigured JdbcTemplate.
spring.datasource.url=jdbc:sqlserver://${DB_SERVER};PortNumber=${DB_PORT};failoverPartner=${DB_FAILOVER_SERVER};databaseName=${DB_NAME};
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driverClassName= com.microsoft.sqlserver.jdbc.SQLServerDriver
But after more that 20 hours of inactivity I see that connection is closed and my web service is blocked.
Does Spring Boot closes all connection in case of inactivity automatically after some time?
EDIT 21 March
If I don't add connection test every X minutes or before taking it from the pool does it mean that jdbcTemplate will not recreate them in cas of long inactivity?
spring.datasource.tomcat.testWhileIdle = true
spring.datasource.tomcat.timeBetweenEvictionRunsMillis = 50000
spring.datasource.tomcat.validationQuery = SELECT 1
Add these values to application.properties file

Default connections hold by JedisPool

I am integrating redis with ofbiz by using jedis client.
One redis server is being used by different application.
My question is
How many connection will be hold by JedisPool by default.
If I create multiple JedisPool will it effect redis performance
Note : I am creating JedisPool with default configuration in another application.
client = new JedisPool(ip, port);
Is there any better approach?, suggest me. Thanks
Update : Initiating redis server with default configuratoin user spring data
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${app.cache.redis.host}" p:port="${app.cache.redis.port}" p:password="${app.cache.redis.password}" />
1) How many connection will be hold by JedisPool by default
By using JedisPool with this instantiation,
client = new JedisPool(ip, port);
you are using a GenericObjectPoolConfig from apache-commons-pool.
The default configuration for this generic pool is:
DEFAULT_MAX_TOTAL = 8
DEFAULT_MAX_IDLE = 8
DEFAULT_MIN_IDLE = 0
2) If I create multiple JedisPool will it effect redis performance
Yes and no. If you create multiple JedisPool, you will have more clients connected to Redis. But Redis can support a lot of connected clients with very good performance.
You can set the Redis max client authorized number in redis.conf (for example 10000 clients max).
maxclients 10000
or at startup :
./redis-server --maxclients 10000
or with redis-cli :
127.0.0.1:6379> config set maxclients 10000
In the default configuration, the number of authorized clients is unlimited.
Depending of your use case, you can have multiple JedisPool, or simply increase the size of your JedisPool (to have more than 8 connections).

Resources