在现代分布式架构中,Session 共享是保障用户体验一致性的核心难题。本文整合单节点 Redis、3 节点哨兵集群、3 节点 Cluster 集群三种方案,结合 Redisson 框架与 Nginx 负载均衡,提供一套可直接落地的 Tomcat Session 共享手册。无论你是测试环境快速验证,还是生产环境高可用部署,都能从中找到适配方案。
核心架构与环境准备
整体架构分为三层:Nginx 作为反向代理与负载均衡入口,将请求分发至多个 Tomcat 节点;Tomcat 节点通过 Redisson 框架将 Session 数据统一存储在 Redis 中;Redis 提供高性能、高可用的数据存储服务。这样设计的好处是:任何 Tomcat 节点宕机或扩缩容,用户的 Session 都不会丢失,实现了真正的无状态化。
下表展示了核心组件及其版本依赖关系,请务必按照此表准备环境:
| 组件 | 角色与作用 |
|---|---|
| Nginx | 前端反向代理,实现 Tomcat 集群负载均衡,转发客户端请求 |
| Tomcat 集群 | ≥2 个节点,提供相同 Web 服务,通过 Redisson 将 Session 存储到 Redis |
| Redisson | Tomcat 与 Redis 的中间件,支持单节点 / 集群 Redis,实现 Session 分布式共享 |
| Redis | 三种部署模式:单节点(测试)、3 节点哨兵(中小规模高可用)、3 节点 Cluster(大规模分片) |
| 组件 | 推荐版本 | 必备资源 |
|---|---|---|
| JDK | 1.8+ | 所有 Tomcat 节点版本一致 |
| Tomcat | 9.0/8.5 | Tomcat9 用,Tomcat8.5 用 |
| Nginx | 1.18+ | 无额外依赖 |
| Redis | 5.0+/6.0+ | 单节点 / 3 节点集群部署 |
| Redisson 包 | 3.20.0 | 1. redisson-all-3.20.0.jar:https://repo1.maven.org/maven2/org/redisson/redisson-all/3.20.0/redisson-all-3.20.0.jar2. redisson-tomcat-9-3.20.0.jar:https://repo1.maven.org/maven2/org/redisson/redisson-tomcat-9/3.20.0/redisson-tomcat-9-3.20.0.jar |
前置操作:将两个 Redisson 包放入所有 Tomcat 节点的 {CATALINA_HOME}/lib 目录,执行 chmod 644 redisson-*.jar 赋予可读权限;同时确保 Nginx 能访问 Tomcat,Tomcat 能访问 Redis,网络互通是基础。
Redis 部署方案(三种模式)
方案 1:单节点 Redis(测试环境)
单节点配置最为简单,适合快速功能验证。配置文件 /etc/redis/redis-6379.conf 内容如下:
bind 0.0.0.0
protected-mode no
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile /var/log/redis/redis-6379.log
dir /var/lib/redis/6379
# 安全与持久化
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
启动与验证命令:
# 创建数据目录
mkdir -p /var/lib/redis/6379 && chown -R redis:redis /var/lib/redis/
# 启动Redis
redis-server /etc/redis/redis-6379.conf
# 验证连接
redis-cli -p 6379 -a 123456 ping # 返回PONG即成功
⚠️ 注意:单节点存在单点故障风险,生产环境请勿使用。
方案 2:3 节点哨兵集群(中小规模高可用)
哨兵模式提供自动故障转移能力,无需额外部署哨兵节点,3 台 Redis 即可组成 1 主 2 从架构。节点规划如下:
| 角色 | 端口 | 配置文件 | 数据目录 |
|---|---|---|---|
| 主节点 | 6379 | redis-6379.conf | /var/lib/redis/6379 |
| 从节点 1 | 6380 | redis-6380.conf | /var/lib/redis/6380 |
| 从节点 2 | 6381 | redis-6381.conf | /var/lib/redis/6381 |
主节点配置与单节点相同,从节点需添加主节点指向:
# 其余配置同主节点,仅新增/修改以下内容
port 6380
pidfile /var/run/redis_6380.pid
logfile /var/log/redis/redis-6380.log
dir /var/lib/redis/6380
# 指向主节点
slaveof 127.0.0.1 6379
port 6381
pidfile /var/run/redis_6381.pid
logfile /var/log/redis/redis-6381.log
dir /var/lib/redis/6381
slaveof 127.0.0.1 6379
启动与验证:
# 创建数据目录
mkdir -p /var/lib/redis/6379 /var/lib/redis/6380 /var/lib/redis/6381 && chown -R redis:redis /var/lib/redis/
# 启动所有节点
redis-server /etc/redis/redis-6379.conf
redis-server /etc/redis/redis-6380.conf
redis-server /etc/redis/redis-6381.conf
# 验证主从同步
redis-cli -p 6379 -a 123456 info replication # 显示connected_slaves:2即成功
✅ 哨兵模式适用于中小规模生产环境,兼顾性能与高可用。
方案 3:3 节点 Cluster 集群(测试用简化版)
Redis Cluster 提供自动分片与高可用,这里采用 3 主 无从的简化配置,适合测试分布式 Session 存储的扩展性。节点规划:
| 角色 | 端口 | 配置文件 | 数据目录 |
|---|---|---|---|
| 主节点 1 | 7000 | redis-7000.conf | /var/lib/redis/7000 |
| 主节点 2 | 7001 | redis-7001.conf | /var/lib/redis/7001 |
| 主节点 3 | 7002 | redis-7002.conf | /var/lib/redis/7002 |
配置文件示例(以 7000 端口为例,其余仅改端口):
bind 0.0.0.0
protected-mode no
port 7000
daemonize yes
pidfile /var/run/redis_7000.pid
logfile /var/log/redis/redis-7000.log
dir /var/lib/redis/7000
# 安全配置
requirepass 123456
masterauth 123456
# Cluster核心配置
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
cluster-require-full-coverage yes
# 持久化
appendonly yes
appendfilename "appendonly-7000.aof"
启动与创建集群:
# 创建数据目录
mkdir -p /var/lib/redis/7000 /var/lib/redis/7001 /var/lib/redis/7002 && chown -R redis:redis /var/lib/redis/
# 启动所有节点
redis-server /etc/redis/redis-7000.conf
redis-server /etc/redis/redis-7001.conf
redis-server /etc/redis/redis-7002.conf
# 创建3主Cluster集群
redis-cli -a 123456 --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 --cluster-replicas 0
# 验证集群状态
redis-cli -c -p 7000 -a 123456 cluster info # 显示cluster_state:ok即成功
延伸思考:在生产环境中,Redis Cluster 通常搭配 6 节点(3 主 3 从)使用,确保数据高可用。对于 MySQL、PostgreSQL 等传统数据库的 Session 持久化场景,Redis 作为缓存层能显著降低数据库压力,这也是数据库优化的重要手段之一。
Redisson 配置:适配所有 Redis 模式
将配置文件放入所有 Tomcat 节点的 {CATALINA_HOME}/conf 目录,根据 Redis 模式选择对应配置。推荐使用 YAML 格式,更易读。
YAML 格式配置
单节点:redisson-single.yaml
singleServerConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: "123456"
address: "redis://127.0.0.1:6379"
database: 0
threads: 16
nettyThreads: 32
codec: ! {}
transportMode: "NIO"
哨兵集群:redisson-sentinel.yaml
sentinelServersConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: "123456"
sentinelAddresses:
- "redis://127.0.0.1:6379"
- "redis://127.0.0.1:6380"
- "redis://127.0.0.1:6381"
masterName: "mymaster"
database: 0
threads: 16
nettyThreads: 32
codec: ! {}
transportMode: "NIO"
Cluster 集群:redisson-cluster.yaml
clusterServersConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: "123456"
nodeAddresses:
- "redis://127.0.0.1:7000"
- "redis://127.0.0.1:7001"
- "redis://127.0.0.1:7002"
scanInterval: 1000
threads: 16
nettyThreads: 32
codec: ! {}
transportMode: "NIO"
JSON 格式配置
单节点:redisson-single.json
{
"singleServerConfig": {
"password": "123456",
"address": "redis://127.0.0.1:6379",
"database": 0
},
"threads": 16,
"nettyThreads": 32,
"codec": {"class":"org.redisson.codec.JsonJacksonCodec"}
}
哨兵集群与 Cluster 集群的 JSON 格式与 YAML 等价,按字段对应转换即可,此处不再赘述。
建议:使用 YAML 格式时,注意缩进规范,否则 Redisson 启动时会报解析错误。
Tomcat 集群配置:核心 Session 共享
端口区分(2 节点示例)
修改 {CATALINA_HOME}/conf/server.xml 中的 3 个核心端口,避免冲突:
| Tomcat 节点 | 关闭端口 | HTTP 端口 | AJP 端口 |
|---|---|---|---|
| Tomcat1 | 8005 | 8080 | 8009 |
| Tomcat2 | 8006 | 8081 | 8010 |
启用 Redisson Session 共享
编辑 {CATALINA_HOME}/conf/context.xml ,在 <Context> 标签内添加配置,根据 Redis 模式选择对应 configPath:
configPath="${catalina.base}/conf/redisson-single.yaml"
readMode="REDIS"
updateMode="AFTER_REQUEST"
/>
统一 Session 超时时间
编辑 {CATALINA_HOME}/conf/web.xml ,设置与 Redisson 一致的超时时间:
30
启动并验证
# 启动Tomcat节点
cd /usr/local/tomcat8080/bin && ./startup.sh
cd /usr/local/tomcat8081/bin && ./startup.sh
# 查看日志,确认无Redis连接错误
tail -f /usr/local/tomcat8080/logs/catalina.out
✅ 所有 Tomcat 节点配置一致,确保 Session 共享机制生效。
Nginx 负载均衡配置
核心配置位于 /usr/local/nginx/conf/nginx.conf :
http {
# Tomcat集群上游配置
upstream tomcat_cluster {
server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 weight=1 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://tomcat_cluster;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
启动与验证:
# 检查配置
/usr/local/nginx/sbin/nginx -t
# 启动/重启
/usr/local/nginx/sbin/nginx -s reload
在数据库优化场景中,Nginx 层的 Session 一致性是保障应用层无状态的基础,配合 MongoDB 或 PostgreSQL 等数据库的分布式事务,可以构建高可用的全栈架构。
整体功能验证
制作测试页面
在所有 Tomcat 的 webapps/ROOT 目录下创建 test-session.jsp :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.net.InetAddress" %>
Nginx+Tomcat+Redis Session共享测试
【SessionID】:<%= session.getId() %>
【当前Tomcat】:<%= InetAddress.getLocalHost().getHostAddress() + ":" + request.getServerPort() %>
【是否新Session】:<%= session.isNew() ? "是" : "否(共享成功)" %>
验证标准
- 浏览器访问
http://Nginx_IP/test-session.jsp; - 刷新页面:SessionID 始终不变,Tomcat 节点在 8080/8081 间切换 → Session 共享成功;
- Redis 端验证:执行
keys redisson:session:*,能查到与页面一致的 Session 键 → 存储成功; - 高可用验证(集群模式):停掉 Redis 主节点,等待 5 秒后刷新页面,SessionID 仍不变 → 故障转移生效。
全局避坑指南(必看)
- Redisson 包版本匹配:Tomcat9 必须用
redisson-tomcat-9,版本不匹配会导致 Tomcat 启动失败; - Redis 密码一致性:所有 Redis 节点、Redisson 配置的密码必须相同,否则连接拒绝;
- 配置文件路径:Redisson 配置文件需放在 Tomcat 的
conf目录,configPath用${catalina.base}/conf/xxx.yaml; - 防火墙开放端口:生产需开放 Nginx80、Tomcat8080/8081、Redis 对应端口(6379/6380/6381 或 7000-7002);
- Session 对象序列化:自定义对象存入 Session 需实现
java.io.Serializable接口,否则序列化失败; - Redis 持久化:所有模式均需开启 AOF+RDB,防止 Redis 重启丢失 Session 数据。
总结:本文从单节点到集群,系统阐述了 Nginx+Tomcat+Redis+Redisson 实现 Session 共享的完整方案。无论你是使用 MySQL 做持久化、PostgreSQL 做复杂查询,还是 MongoDB 做文档存储,Session 共享都是分布式架构的基石。建议从单节点测试开始,逐步过渡到哨兵或 Cluster 集群,并严格遵循避坑指南,确保生产环境稳定可靠。
redisson-tomcat-9redisson-tomcat-8
浙公网安备 33010602011771号