iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >怎么解决redis中分布式session不一致性
  • 624
分享到

怎么解决redis中分布式session不一致性

2024-04-02 19:04:59 624人浏览 独家记忆
摘要

这篇文章主要讲解了“怎么解决Redis中分布式session不一致性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决redis中分布式session不

这篇文章主要讲解了“怎么解决Redis分布式session不一致性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决redis中分布式session不一致性”吧!

怎么解决redis中分布式session不一致性

分布式session不一致性解决方案

一、Session有什么作用?

  • Session 是客户端与服务器通讯会话跟踪技术,服务器与客户端保持整个通讯的会话基本信息。【相关推荐:Redis视频教程

  • 客户端在第一次访问服务端的时候,服务端会响应一个sessionId并且将它存入到本地cookie中,在之后的访问会将cookie中的sessionId放入到请求头中去访问服务器,

  • 如果通过这个sessionId没有找到对应的数据,那么服务器会创建一个新的sessionId并且响应给客户端。

二、分布式Session有什么问题?

单服务器WEB应用中,session信息只需存在该服务器中,这是我们前几年最常接触的方式

但是近几年随着分布式系统的流行,单系统已经不能满足日益增长的百万级用户的需求,集群方式部署服务器已在很多公司运用起来

高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到session数据的情况,于是session的共享就成了一个问题。

怎么解决redis中分布式session不一致性

三、服务做集群一般是怎么样做的?

四、nginx负载均衡和ribbon负载均衡的区别

  • nginx做负载均衡是服务器端的负载均衡,统一访问一个地址,根据负载均衡算法访问决定访问那一个服务器。

  • ribbon负载均衡,这是本地负载均衡(客户端负载均衡),把提供服务的客户端地址都缓存记录下来,根据本地的算法实现负载均衡。

五、Session一致性解决方案

1. session复制(同步)

怎么解决redis中分布式session不一致性

思路:多个服务端之间相互同步session,这样每个服务端之间都包含全部的session

优点:服务端支持的功能,应用程序不需要修改代码

缺点:

  • session的同步需要数据传输,占内网带宽,有时延

  • 所有服务端都包含所有session数据,数据量受内存限制,无法水平扩展

2. 客户端存储法

怎么解决redis中分布式session不一致性

思路:服务端存储所有用户的session,内存占用较大,可以将session存储到浏览器cookie中,每个端只要存储一个用户的数据了

优点:服务端不需要存储

缺点:

  • 每次Http请求都携带session,占外网带宽

  • 数据存储在端上,并在网络传输,存在泄漏、篡改、窃取等安全隐患

  • session存储的数据大小和域名cookie个数都受限制的

注:该方案虽然不常用,但确实是一种思路。

3. 反向代理hash一致性

思路:服务端为了保证高可用,有多台冗余,反向代理层能不能做一些事情,让同一个用户的请求保证落在一台服务端上呢?

方案一:四层代理hash

怎么解决redis中分布式session不一致性

反向代理层使用用户的ip来做hash,以保证同一个ip的请求落在同一个服务端上

方案二:七层代理hash

怎么解决redis中分布式session不一致性

反向代理使用http协议中的某些业务属性来做hash,例如sid,city_id,user_id等,能够更加灵活的实施hash策略,以保证同一个浏览器用户的请求落在同一个服务器上

优点:

  • 只需要改nginx配置,不需要修改应用代码

  • 负载均衡,只要hash属性是均匀的,多台服务端的负载是均衡的

  • 可以支持服务端水平扩展(session同步法是不行的,受内存限制)

缺点:

  • 如果服务端重启,一部分session会丢失,产生业务影响,例如部分用户重新登录

  • 如果服务端水平扩展,rehash后session重新分布,也会有一部分用户路由不到正确的session

session一般是有有效期的,所有不足中的两点,可以认为等同于部分session失效,一般问题不大。

对于四层hash还是七层hash,个人推荐前者:让专业的软件做专业的事情,反向代理就负责转发,尽量不要引入应用层业务属性,除非不得不这么做(例如,有时候多机房多活需要按照业务属性路由到不同机房的服务器)。

四层、七层负载均衡的区别

4. 后端统一集中存储

怎么解决redis中分布式session不一致性

优点:

  • 没有安全隐患

  • 可以水平扩展,数据库/缓存水平切分即可

  • 服务端重启或者扩容都不会有session丢失

不足:增加了一次网络调用,并且需要修改应用代码

对于db存储还是cache,个人推荐后者:session读取的频率会很高,数据库压力会比较大。如果有session高可用需求,cache可以做高可用,但大部分情况下session可以丢失,一般也不需要考虑高可用。

总结

保证session一致性的架构设计常见方法:

  • session同步法:多台服务端相互同步数据

  • 客户端存储法 一个用户只存储自己的数据

  • 反向代理hash一致性 四层hash和七层hash都可以做,保证一个用户的请求落在一台服务端上

  • 后端统一存储 服务端重启和扩容,session也不会丢失(推荐后端cache统一存储)

六、案例实战:SpringSession+redis解决分布式session不一致性问题

步骤1:加入SpringSession、redis的依赖包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

步骤2:配置文件

# 为某个包目录下 设置日志
logging.level.com.ljw=debug

# 设置session的存储方式,采用redis存储
spring.session.store-type=redis
# session有效时长为10分钟
server.servlet.session.timeout=PT10M

## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.passWord=

步骤3: 配置拦截器

@Configuration
public class SessionConfig implements WebmvcConfigurer {

    @Override
    public void addInterceptors(InterceptorReGIStry registry) {
        registry.addInterceptor(new SecurityInterceptor())
                //排除拦截的2个路径
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/loGout")
                //拦截所有URL路径
                .addPathPatterns("
    @GetMapping(value = "/find/{username}")
    public User find(@PathVariable String username) {
        User user=this.userMap.get(username);
        log.info("通过用户名={},查找出用户{}",username,user);
        return user;
    }

    
    @GetMapping(value = "/session")
    public String session(httpsession session) {
        log.info("当前用户的session={}",session.getId());
        return session.getId();
    }

    
    @GetMapping(value = "/logout")
    public String logout(HttpSession session) {
        log.info("退出登录session={}",session.getId());
        session.removeAttribute(session.getId());
        return "成功退出!!";
    }

}

步骤5: 实体类

@Data
public class User implements  Serializable{

    private int id;
    private String username;
    private String password;

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

}

步骤6:访问测试

先登录:http://127.0.0.1:8080/user/login?username=user1&password=user1

再查询http://127.0.0.1:8080/user/find/user1

七、剖析SpringSession的redis原理

步骤1:分析SpringSession的redis数据结构

127.0.0.1:6379> keys *
1) "spring:session:sessions:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a"
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b"
3) "spring:session:expirations:1635413520000"
4) "spring:session:sessions:expires:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a"
5) "spring:session:expirations:1635412980000"
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"

共同点:3个key都是以spring:session:开头的,代表了SpringSession的redis数据。

查询类型

127.0.0.1:6379> type spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b
hash
127.0.0.1:6379> hgetall spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b
// session的创建时间
1) "creationTime"
2) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xdb\xecu"
// sesson的属性,存储了user对象
3) "sessionAttr:d3434f61-4d0a-4687-9070-610bd7790f3b"
4) "\xac\xed\x00\x05sr\x00\x1ecom.ljw.redis.controller.User\x16\"_m\x1b\xa0W\x7f\x02\x00\x03I\x00\x02idL\x00\bpasswordt\x00\x12Ljava/lang/String;L\x00\busernameq\x00~\x00\x01xp\x00\x00\x00\x01t\x00\x05user1q\x00~\x00\x03"
//最后的访问时间
5) "lastAccessedTime"
6) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xe1\xc7\xed"
//失效时间 100分钟
7) "maxInactiveInterval"
8) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x17p"

步骤2:分析SpringSession的redis过期策略

对于过期数据,一般有三种删除策略:

  • 定时删除,即在设置键的过期时间的同时,创建一个定时器, 当键的过期时间到来时,立即删除。

  • 惰性删除,即在访问键的时候,判断键是否过期,过期则删除,否则返回该键值。

  • 定期删除,即每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

  • redis删除过期数据采用的是懒性删除+定期删除组合策略,也就是数据过期了并不会及时被删除。

  • 但由于redis是单线程,并且redis对删除过期的key优先级很低;如果有大量的过期key,就会出现key已经过期但是未删除。

  • 为了实现 session 过期的及时性,spring session 采用了定时删除+惰性删除的策略。

定时删除

127.0.0.1:6379> type spring:session:expirations:1635413520000
set
127.0.0.1:6379> smembers  spring:session:expirations:1635413520000
1) "\xac\xed\x00\x05t\x00,expires:d3434f61-4d0a-4687-9070-610bd7790f3b"
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 
3) "spring:session:expirations:1635413520000" 
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"
  • 1635412980000 是时间戳,等于 2021-10-28 17:23:00,即是该可以在这个时刻过期

  • springsession 定时(1分钟)轮询,删除spring:session:expirations:[?] 的过期成员元素,例如:spring:session:expirations:1635413520000

  • springsesion 定时检测超时的key的值,根据值删除seesion,例如key:spring:session:expirations:1635413520000,值为(sessionId):d3434f61-4d0a-4687-9070-610bd7790f3b的seesion

惰性删除

127.0.0.1:6379> type spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
string
127.0.0.1:6379> get spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
""
127.0.0.1:6379> ttl spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
(integer) 3143
127.0.0.1:6379>
  • 访问 spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b的时候,判断key是否过期,过期则删除,否则返回改进的值。

  • 例如 访问spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b的时候,判断 ttl 是否过期,过期就直接删除

2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 
3) "spring:session:expirations:1635413520000" 
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"

感谢各位的阅读,以上就是“怎么解决redis中分布式session不一致性”的内容了,经过本文的学习后,相信大家对怎么解决redis中分布式session不一致性这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: 怎么解决redis中分布式session不一致性

本文链接: https://www.lsjlt.com/news/65624.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么解决redis中分布式session不一致性
    这篇文章主要讲解了“怎么解决redis中分布式session不一致性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决redis中分布式session不...
    99+
    2024-04-02
  • Java分布式系统中session一致性问题怎么解决
    小编给大家分享一下Java分布式系统中session一致性问题怎么解决,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java可以用来干什么Java主要应用于:1....
    99+
    2023-06-14
  • 如何分析分布式session解决方案与一致性hash
    这篇文章将为大家详细讲解有关如何分析分布式session解决方案与一致性hash,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、问题的提出1. 什么是Session?用户使用网站的服务,需...
    99+
    2023-06-04
  • 详解Java分布式系统中session一致性问题
    业务场景 在单机系统中,用户登陆之后,服务端会保存用户的会话信息,只要用户不退出重新登陆,在一段时间内用户可以一直访问该网站,无需重复登陆。用户的信息存在服务端的 session 中...
    99+
    2024-04-02
  • redis分布式锁解决缓存双写一致性
    目录如何解决缓存双写问题业务背景-美食分享分布式锁查询修改如何解决缓存双写问题 只要涉及到缓存,那么缓存双写的问题就避免不了,每一种情况下使用的方案也不相同,对于数据一致性要求不高的...
    99+
    2023-05-19
    分布式锁解决缓存双写一致性 分布式锁缓存双写问题
  • 有哪些分布式一致性Session实现方式
    本篇内容介绍了“有哪些分布式一致性Session实现方式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言...
    99+
    2024-04-02
  • redis怎么实现分布式session
    Redis可以通过以下几步来实现分布式session:1. 创建一个Redis服务器集群:可以使用Redis Sentinel或Re...
    99+
    2023-09-20
    redis
  • redis并发读写不一致性怎么解决
    在Redis中,并发读写不一致性主要指的是在多线程或多进程环境下,可能会出现读取到脏数据或写入数据丢失的情况。为了解决这个问题,可以...
    99+
    2023-09-01
    redis
  • Redis如何实现分布式缓存一致性
    Redis如何实现分布式缓存一致性,需要具体代码示例缓存是提高系统性能的重要手段之一,而分布式缓存则能够进一步提升系统的并发能力和扩展性。Redis作为一种常用的内存数据库,具有快速、高效的特点,广泛被用于分布式缓存的实现。在分布式缓存中,...
    99+
    2023-11-07
    缓存 分布式 redis
  • 利用Redis实现分布式缓存一致性
    利用Redis实现分布式缓存一致性在现代分布式系统中,缓存起着非常重要的作用。它可以大大降低系统对数据库的访问频率,提高系统的性能和吞吐量。而在分布式系统中,为了保证缓存的一致性,我们需要解决多个节点之间的数据同步问题。在本文中,我们将介绍...
    99+
    2023-11-07
    缓存 分布式 redis
  • redis实现分布式session的解决方案
    目录一、首先Session二、分布式Session补充:一、首先Session Session 是客户端与服务器通讯会话技术, 比如浏览器登陆、记录整个浏览会话信息。session存...
    99+
    2024-04-02
  • redis怎么解决数据一致性
    redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一...
    99+
    2024-04-08
    redis
  • 怎么解决分布式session问题
    本篇内容介绍了“怎么解决分布式session问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!sessio...
    99+
    2024-04-02
  • Redis如何实现分布式事务的一致性
    Redis是一个高性能、分布式内存数据库,被广泛应用在分布式系统中。在分布式系统中,如何实现事务的一致性一直是一个难题,而Redis提供的事务机制可以帮助开发者解决这个问题。本文将介绍Redis如何实现分布式事务的一致性,并展示代码示例。一...
    99+
    2023-11-07
    redis 分布式事务 一致性
  • Spring Boot/Spring Session/Redis的分布式Session共享如何解决
    本篇文章为大家展示了Spring Boot/Spring Session/Redis的分布式Session共享如何解决,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。分布式Web网站一般都会碰到集群s...
    99+
    2023-05-31
    springboot spring session redis
  • 如何使用Redis实现分布式数据一致性
    如何使用Redis实现分布式数据一致性引言:随着互联网的快速发展,分布式系统已成为许多企业的首选架构。在分布式系统中,数据的一致性是非常关键的。Redis作为一种高性能、可扩展的键值存储系统,被广泛应用于分布式系统中,下面将介绍如何使用Re...
    99+
    2023-11-07
    分布式 redis 一致性
  • 跨地域场景下,怎么解决分布式系统的一致性
    这篇文章主要讲解了“跨地域场景下,怎么解决分布式系统的一致性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“跨地域场景下,怎么解决分布式系统的一致性”吧!一 ...
    99+
    2024-04-02
  • Redis集群中的一致性问题怎么解决
    在Redis集群中,一致性问题可以通过以下方式来解决: 使用主从复制:通过在Redis集群中设置主节点和从节点,主节点负责处理写...
    99+
    2024-04-29
    Redis
  • redis缓存一致性问题怎么解决
    在使用 Redis 缓存时,可能会遇到缓存一致性问题,即缓存中的数据与数据库中的数据不一致。以下是一些常见的解决方法: 缓存更新...
    99+
    2023-10-26
    redis
  • redis和mysql数据不一致怎么解决
    解决 redis 和 mysql 数据不一致的方法包括:确定数据不一致的根源。协调数据一致性:事务性更新、分布式锁、事件驱动的更新。数据同步:异步复制、定期同步、增量同步。数据验证:定期...
    99+
    2024-04-08
    mysql redis 同步机制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作