Redis-based Session Sharing
Redis is an in-memory data store capable of handling hundreds of thousands of reads/writes per second. When all Tomcat instances share a single Redis as a common session store, any server can access the same session regardless of which server handled the original login.
Redis Session Architectureβ
[Client]
β
[Load Balancer]
βββ [App1: Tomcat] ββΆ ββββββββββββββββ
βββ [App2: Tomcat] ββΆ β Redis β
βββ [App3: Tomcat] ββΆ β Session β
β Store β
ββββββββββββββββ
All Tomcat instances save and retrieve sessions from the same Redis. No matter which server handles a request, it reads the same session from Redis.
Redis Installation and Configurationβ
# Ubuntu
sudo apt-get install redis-server
# CentOS
sudo yum install redis
# Start
sudo systemctl enable --now redis
# Verify connection
redis-cli ping
# PONG
Optimized Redis Configuration for Sessionsβ
# /etc/redis/redis.conf
# Allow external connections (if needed)
bind 0.0.0.0
# Set password (required)
requirepass your-strong-password-here
# Auto-clean sessions when memory is full
maxmemory 2gb
maxmemory-policy allkeys-lru
# Disable persistence (not needed for session-only use)
save ""
appendonly no
Option 1: Tomcat Redis Session Managerβ
Replaces Tomcat's default session manager with a Redis-backed one.
Add Dependenciesβ
# Copy JARs to Tomcat lib folder
wget https://github.com/jcoleman/tomcat-redis-session-manager/releases/download/2.0.0/tomcat-redis-session-manager-2.0.0.jar
cp tomcat-redis-session-manager-2.0.0.jar /opt/tomcat/lib/
wget https://repo1.maven.org/maven2/redis/clients/jedis/4.4.3/jedis-4.4.3.jar
cp jedis-4.4.3.jar /opt/tomcat/lib/
wget https://repo1.maven.org/maven2/org/apache/commons/commons-pool2/2.11.1/commons-pool2-2.11.1.jar
cp commons-pool2-2.11.1.jar /opt/tomcat/lib/
context.xml Configurationβ
<!-- /opt/tomcat/conf/context.xml -->
<Context>
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"/>
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="10.0.0.10"
port="6379"
password="your-strong-password-here"
database="0"
maxInactiveInterval="1800"
sessionPersistPolicies="SAVE_ON_CHANGE"
/>
</Context>
Option 2: Spring Session + Redis (Recommended)β
The easiest and most reliable approach for Spring Boot applications. One annotation switches the session store to Redis.
Dependencies (build.gradle)β
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.session:spring-session-data-redis'
}
application.ymlβ
spring:
data:
redis:
host: 10.0.0.10
port: 6379
password: your-strong-password-here
timeout: 2000ms
lettuce:
pool:
max-active: 10
max-idle: 5
min-idle: 1
max-wait: 1000ms
session:
store-type: redis
timeout: 30m
redis:
namespace: myapp
flush-mode: on-save
SessionConfig.javaβ
@Configuration
@EnableRedisHttpSession(
maxInactiveIntervalInSeconds = 1800,
redisNamespace = "myapp:session"
)
public class SessionConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
GenericJackson2JsonRedisSerializer jsonSerializer =
new GenericJackson2JsonRedisSerializer();
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
}
Controller Exampleβ
@RestController
public class AuthController {
@PostMapping("/login")
public ResponseEntity<String> login(
@RequestBody LoginRequest request,
HttpSession session) {
User user = authService.authenticate(request.getUsername(), request.getPassword());
// Stored in session β automatically saved to Redis
session.setAttribute("userId", user.getId());
session.setAttribute("username", user.getUsername());
session.setAttribute("role", user.getRole());
session.setMaxInactiveInterval(1800);
return ResponseEntity.ok("Login successful");
}
@GetMapping("/profile")
public ResponseEntity<UserProfile> getProfile(HttpSession session) {
Long userId = (Long) session.getAttribute("userId");
if (userId == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
// Same session retrieved from Redis regardless of which server handles this
UserProfile profile = userService.findById(userId);
return ResponseEntity.ok(profile);
}
@PostMapping("/logout")
public ResponseEntity<Void> logout(HttpSession session) {
session.invalidate(); // Deletes session from Redis
return ResponseEntity.ok().build();
}
}
Inspecting Redis Session Dataβ
# List session keys in Redis
redis-cli -h 10.0.0.10 -a your-password KEYS "myapp:session*"
# View session contents
redis-cli -h 10.0.0.10 -a your-password HGETALL "myapp:session:sessions:1a2b3c4d"
# Check session TTL (seconds remaining until expiry)
redis-cli -h 10.0.0.10 -a your-password TTL "myapp:session:sessions:1a2b3c4d"
# Force-delete a specific session (admin action)
redis-cli -h 10.0.0.10 -a your-password DEL "myapp:session:sessions:1a2b3c4d"
Redis High Availability: Sentinel and Clusterβ
Redis Sentinel (Automatic Failover)β
# application.yml
spring:
data:
redis:
sentinel:
master: mymaster
nodes:
- 10.0.0.10:26379
- 10.0.0.11:26379
- 10.0.0.12:26379
password: sentinel-password
password: redis-password
Redis Cluster (Horizontal Scaling)β
spring:
data:
redis:
cluster:
nodes:
- 10.0.0.10:7001
- 10.0.0.10:7002
- 10.0.0.11:7003
- 10.0.0.11:7004
- 10.0.0.12:7005
- 10.0.0.12:7006
max-redirects: 3
password: redis-cluster-password
Performance Comparison: Session Strategiesβ
Local session (single server) : ~0.1ms (direct memory access)
Tomcat clustering : ~1~5ms (includes network replication)
Redis session (local) : ~0.5ms (Redis loopback)
Redis session (remote) : ~1~2ms (one network round trip)
Redis Cluster : ~2~5ms (includes cluster routing)
The additional latency from Redis session lookups β typically 1~2ms β is negligible compared to business logic processing time (tens to hundreds of milliseconds).
The next page covers session serialization principles and performance optimization.