分布式系列教程(15) - 解决分布式Session一致性问题

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
应用型负载均衡 ALB,每月750个小时 15LCU
简介: 分布式系列教程(15) - 解决分布式Session一致性问题

引言

何为Session?

Session 是客户端与服务器通讯会话技术, 比如浏览器登陆、记录整个浏览会话信息。

Session原理:客户对向服务器端发送请求后,Session 创建在服务器端,返回Sessionid给客户端浏览器保存在本地,当下次发送请求的时候,在请求头中传递sessionId获取对应的从服务器上获取对应的Sesison对象。Session是保存在服务器的,及时关闭服务器。

熟悉下相关代码:

@SpringBootApplication
@RestController
public class TestSessionController {
  // 创建session 会话
  @RequestMapping("/createSession")
  public String createSession(HttpServletRequest request, String nameValue) {
    HttpSession session = request.getSession();
    System.out.println("存入Session  sessionid:信息" + session.getId() + ",nameValue:" + nameValue);
    session.setAttribute("name", nameValue);
    return "success";
  }
  // 获取session 会话
  @RequestMapping("/getSession")
  public Object getSession(HttpServletRequest request) {
    HttpSession session = request.getSession();
    System.out.println("获取Session sessionid:信息" + session.getId());
    Object value = session.getAttribute("name");
    return value;
  }
  public static void main(String[] args) {
    SpringApplication.run(TestSessionController.class, args);
  }
}

引出问题:当服务器集群时,如果服务器产生了集群后,因为session是存放在服务器上,客户端会使用同一个Sessionid在多个不同的服务器上获取对应的Session,从而会导致Session不一致问题,那么该如何解决呢?

答:可以通过nginx或者haproxy实现IP绑定来解决Session一致性的问题 。

先看看Nginx相关配置:

1.Nginx负载均衡配置

Nginx负载均衡提供上游服务器(真实业务逻辑访问的服务器),负载均衡、故障转移、失败重试、容错、健康检查等。

当上游服务器(真实业务逻辑访问的服务器)发生故障时,可以转移到其他上游服务器(真实业务逻辑访问的服务器)。

upstream 主要配置如下(配置上游服务器的IP地址和端口):

###定义上游服务器(需要被nginx真实代理访问的服务器) 默认是轮训机制
upstream  backServer{
 server 127.0.0.1:8080;
 server 127.0.0.1:8081;
}
server {
       listen       80;
       server_name  www.xxx.com;
       location / {
      ### 指定上游服务器负载均衡服务器
      proxy_pass http://backServer;
           index  index.html index.htm;
       }
   }

1.1 负载均衡算法

  • 轮询(默认): 每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响。
  • weight(轮询权值):weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。或者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。
  • ip_hash :每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题,俗称IP绑定。
  • fair(第三方):比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。
  • url_hash(第三方):按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身不支持url_hash,如果需要这种调度算法,则必须安装Nginx的hash软件包。

2.分布式Session一致性解决方案

文章开头前已经提出了解决方案,解决Session一致性问题,可以使用Nginx或者Haproxy的IP绑定来处理:

  • Nginx:用Nginx 做的负载均衡可以添加ip_hash这个配置
  • Haproxy:用haproxy做的负载均衡可以用 balance source这个配置

使用Nginx和Haproxy是偏向于运营人员的,那么开发这边要怎么处理呢?其实最靠谱的分布式Session一致性解决方案是“基于令牌的方式”,因为Session本身就是分布式共享链接。

简单的来说,就是把Session保存到Redis服务器,token有服务端生成,通过token从Redis服务器获取Session对象,其伪代码如下:

1.TokenService:

@Service
public class TokenService {
  @Autowired
  private RedisService redisService;
  // 新增 返回token
  public String put(Object object) {
    String token = getToken();
    redisService.setString(token, object);
    return token;
  }
  // 获取信息
  public String get(String token) {
    String reuslt = redisService.getString(token);
    return reuslt;
  }
  public String getToken() {
    return UUID.randomUUID().toString();
  }
}

TokenController :

@RestController
public class TokenController {
  @Autowired
  private TokenService tokenService;
  @Value("${server.port}")
  private String serverPort;
  @RequestMapping("/put")
  public String put(String nameValue) {
    String token = tokenService.put(nameValue);
    return token + "-" + serverPort;
  }
  @RequestMapping("/get")
  public String get(String token) {
    String value = tokenService.get(token);
    return value + "-" + serverPort;
  }
}

总结

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
7天前
|
存储 缓存 负载均衡
一致性哈希:解决分布式难题的神奇密钥
一致哈希是一种特殊的哈希算法,用于分布式系统中实现数据的高效、均衡分布。它通过将节点和数据映射到一个虚拟环上,确保在节点增减时只需重定位少量数据,从而提供良好的负载均衡、高扩展性和容错性。相比传统取模方法,一致性哈希能显著减少数据迁移成本,广泛应用于分布式缓存、存储、数据库及微服务架构中,有效提升系统的稳定性和性能。
44 1
|
2月前
|
存储 缓存 NoSQL
分布式架构下 Session 共享的方案
【10月更文挑战第15天】在实际应用中,需要根据具体的业务需求、系统架构和性能要求等因素,选择合适的 Session 共享方案。同时,还需要不断地进行优化和调整,以确保系统的稳定性和可靠性。
|
2月前
|
SQL NoSQL MongoDB
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
53 0
|
3月前
|
存储 NoSQL Java
使用springSession完成分布式session
本文介绍了如何使用 `spring-session` 实现分布式 Session 管理,并提供了将 Session 存储在 Redis 中的具体配置示例。通过配置相关依赖及 Spring 的配置文件,可以轻松实现 Session 的分布式存储。示例中详细展示了所需的 Maven 依赖、Spring 配置及过滤器配置,并给出了启动项目后在 Redis 中查看 Session 数据的方法。
|
2月前
|
消息中间件 缓存 算法
分布式系列第一弹:分布式一致性!
分布式系列第一弹:分布式一致性!
|
2月前
|
算法 Java 关系型数据库
漫谈分布式数据复制和一致性!
漫谈分布式数据复制和一致性!
|
4月前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
4月前
|
存储 算法 NoSQL
(七)漫谈分布式之一致性算法下篇:一文从根上儿理解大名鼎鼎的Raft共识算法!
Raft通过一致性检查,能在一定程度上保证集群的一致性,但无法保证所有情况下的一致性,毕竟分布式系统各种故障层出不穷,如何在有可能发生各类故障的分布式系统保证集群一致性,这才是Raft等一致性算法要真正解决的问题。
127 11
|
4月前
|
存储 算法 索引
(六)漫谈分布式之一致性算法上篇:用二十六张图一探Raft共识算法奥妙之处!
现如今,大多数分布式存储系统都投向了Raft算法的怀抱,而本文就来聊聊大名鼎鼎的Raft算法/协议!
139 8
|
4月前
|
Oracle 关系型数据库
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决
分布式锁设计问题之Oracle RAC保证多个节点写入内存Page的一致性如何解决

热门文章

最新文章