分布式系统要做到用户友好,需要对用户的session进行存储,存储的方式有以下几种:

  1. 本地缓存

  2. 数据库

  3. 文件

  4. 缓存服务器

可以看一些不同方案的优缺点

1.本地机器或者本地缓存。优点:速度快  缺点:服务宕机后重启用户信息丢失,用户不优好

2.数据库。优点:技术栈简单  缺点:速度慢

3.文件。优点:技术栈简单,速度适中 缺点:无灾备或者灾备方案成本高

4.缓存服务器。一般是内存服务器,优点:速度快 可以和原有技术栈契合,有现成的解决方案。缺点:不明显

如果使用java语言,并且缓存服务器为redis,可以使用开源的spring session项目来解决。

spring session项目现有三个自项目,分别是

spring-session-data-redis  使用redis方式

spring-session-hazelcast   使用hazelcast方式

spring-session-jdbc  使用jdbc方式

在这里我建议大家使用redis方式,它提供了注解式和编程式不同的方法。具体如何使用,网上有很多实例,我就不赘述。我想和大家一起深入内部看一下,spring-session项目的github地址为:https://github.com/spring-projects/spring-session.git

我们只看spring-session-data-redis,实现非常简单。它总共只有12个类

核心类只有一个

RedisOperationsSessionRepository

这个类内部定义了session的实现

RedisSession
/** * A custom implementation of {@link Session} that uses a {@link MapSession} as the * basis for its mapping. It keeps track of any attributes that have changed. When * {@link org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession#saveDelta()} * is invoked all the attributes that have been changed will be persisted. * * @author Rob Winch * @since 1.0 */
final class RedisSession implements Session {   private final MapSession cached;   private Instant originalLastAccessTime;   private Map<String, Object> delta = new HashMap<>();   private boolean isNew;   private String originalPrincipalName;   private String originalSessionId;
注意:
delta 是增量 cached是存量

我们来看这个RedisSession的创建 销毁及修改

RedisSession内部存储如下(示例)

* <pre>* HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 maxInactiveInterval 1800 lastAccessedTime 1404360000000 sessionAttr:attrName someAttrValue sessionAttr2:attrName someAttrValue2* EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100* APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""* EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800* SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe* EXPIRE spring:session:expirations1439245080000 2100* </pre>

RedisSession的数据结构是Hash

* <p>* Each session is stored in Redis as a* <a href="http://redis.io/topics/data-types#hashes">Hash</a>. Each session is set and* updated using the <a href="http://redis.io/commands/hmset">HMSET command</a>. An* example of how each session is stored can be seen below.* </p>

RedisSession的失效

* <h3>Expiration</h3>** <p>* An expiration is associated to each session using the* <a href="http://redis.io/commands/expire">EXPIRE command</a> based upon the* {@link org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession#getMaxInactiveInterval()}* . For example:* </p>

RedisSession的更新有一个比较重要的方法:

/** * Saves any attributes that have been changed and updates the expiration of this * session. */private void saveDelta() {   String sessionId = getId();   saveChangeSessionId(sessionId);   if (this.delta.isEmpty()) {      return;   }   getSessionBoundHashOperations(sessionId).putAll(this.delta);   String principalSessionKey = getSessionAttrNameKey(         FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);   String securityPrincipalSessionKey = getSessionAttrNameKey(         SPRING_SECURITY_CONTEXT);   if (this.delta.containsKey(principalSessionKey)         || this.delta.containsKey(securityPrincipalSessionKey)) {      if (this.originalPrincipalName != null) {         String originalPrincipalRedisKey = getPrincipalKey(               this.originalPrincipalName);         RedisOperationsSessionRepository.this.sessionRedisOperations               .boundSetOps(originalPrincipalRedisKey).remove(sessionId);      }      String principal = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this);      this.originalPrincipalName = principal;      if (principal != null) {         String principalRedisKey = getPrincipalKey(principal);         RedisOperationsSessionRepository.this.sessionRedisOperations               .boundSetOps(principalRedisKey).add(sessionId);      }   }

   this.delta = new HashMap<>(this.delta.size());

   Long originalExpiration = (this.originalLastAccessTime != null)         ? this.originalLastAccessTime.plus(getMaxInactiveInterval())               .toEpochMilli()         : null;   RedisOperationsSessionRepository.this.expirationPolicy         .onExpirationUpdated(originalExpiration, this);}

小结:

1.session是键值对形式的,对应redis的数据结构hash

2.session的存储形式使用redis非常方便

转载于:https://www.cnblogs.com/davidwang456/p/10172841.html

spring-session-data-redis解决session共享的问题相关推荐

  1. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  2. 使用Spring Session和Redis解决分布式Session跨域共享问题

    大家可以关注一下公众号"Java架构师秘籍" 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载 ...

  3. Spring boot - 使用redis实现session共享

    在分布式系统架构的系统中,我们如何保证session的一致性,其中之一的解决方式就是session共享形式,在SpringBoot框架中如何使用session达成共享呢,我们可以借助指定Redis实现 ...

  4. Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析

    Springboot鼓励零配置的方式,帮你做好大部分重复劳动的事,好到不能再好:具体的Redis安装方法和Springboot集成Redis方法,可以去搜索相关文章或参考该文章http://www.c ...

  5. php session存到redis,php Session存储到Redis的方法

    php Session存储到Redis的方法 当然要写先安装php的扩展,可参考这篇文章:Redis及PHP扩展安装修改php.ini的设置 复制代码 代码如下: session.save_handl ...

  6. spring boot 整合redis实现session共享

    目录 官方文档,它是spring session项目的redis相关的一个子文档:https://docs.spring.io/spring-session/docs/2.0.0.BUILD-SNAP ...

  7. Spring mvc Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  8. 单点登录实现(spring session+redis完成session共享)

    一.前言 项目中用到的SSO,使用开源框架cas做的.简单的了解了一下cas,并学习了一下 单点登录的原理,有兴趣的同学也可以学习一下,写个demo玩一玩. 二.工程结构 我模拟了 sso的客户端和s ...

  9. spring session通过redis存储,实现session共享

    目录 前言 1 准备工作 1.1 spring框架的jar包 1.2 spring session的相关jar包 2 具体步骤 2.1 创建项目 2.2 spring mvc的配置 2.3 sprin ...

  10. spring-session用redis实现session共享实践

    什么是spring session? Spring Session provides an API and implementations for managing a user's session ...

最新文章

  1. Windows Phone开发:常用控件(上)
  2. Android中的各种Adapter
  3. 部署在SAP ABAP服务器上的SAP UI5应用的JavaScript文件,是如何被SAP UI5 repository handler处理的
  4. java中你知道的这四种代码块吗?
  5. Android点击返回键销毁自己,Activity界面销毁 软键盘未收回
  6. 空字符python_Python中的None与 NULL(即空字符)的区别详解
  7. anaconda安装pytorch1.7.1和torchvision0.8.2的方法,亲测可用
  8. 都在夸官方文档 Vue.js 2021 年度报告出炉!
  9. Python开源机器学习项目实战
  10. html设置字体样式罗马,罗马字体英文
  11. 复工后的前端学习建议,非常实用!
  12. 山东大学——国际结算方式
  13. [美国]《冰雪奇缘》[BD-RMVB.720p.中英双字][2013年高分获奖][奥斯卡提名动画片]
  14. matlab中counter怎么用,matlab中fspecial函数的用法
  15. sudo no tty present and no askpass program specified
  16. 【转】deepin Linux下Picked up _JAVA_OPTIONS错误
  17. Spark之spark VS MR
  18. 云计算事业部高性能集群使用手册
  19. 数学基础:斜率、正切与 math.tan()
  20. 是一个新的开始,还是冥冥之中已经在路上。

热门文章

  1. Spring第三讲:利用注解配置类取代Spring的配置文件
  2. java 链接占用太多_Java程序链接数过多导致java.net.SocketException: No buffer space available问题...
  3. php在页面循环输出标签,自定义页面循环
  4. alertdialog怎么水平排列_轻钢二级吊顶怎么安装
  5. 我的同学是计算机作文,同学相见作文
  6. mongodb聚合查询优化_MongoDB聚合查询详解
  7. android8.1状态栏图标,Android 8.1 去掉 Launcher3 默认给 icon 增加的白边
  8. Fragment碎片的基本使用(手机平板需要更好地兼容)
  9. 8种相似度度量方式的原理及实现【笔记自用】【1】
  10. c++   string类