SpringCloud(28. 分布式会话与分布式事务)

news2024/12/24 8:09:18

上一篇:27. Redis 和 ZK 分布式锁

文章目录

  • 1. 集群部署时的分布式 session 如何实现?
  • 2. 分布式事务方案
    • 2.1 两阶段提交方案/XA方案
    • 2.2 TCC 方案
    • 2.3 本地消息表
    • 2.4 可靠消息最终一致性方案
    • 2.5 最大努力通知方案

1. 集群部署时的分布式 session 如何实现?

1. 完全不用 session

  • 使用 JWT Token 储存用户身份,然后再从数据库或者 cache 中获取其他的信息。这样无论请求分配到哪个服务器都无所谓。

2. tomcat + redis
- 使用 Tomcat RedisSessionManager ,让所有我们部署的 tomcat 都将 session 数据存储到 redis 即可。
- 该方法与 Tomcat 高耦合,较少使用

3. spring session + redis

  • 现在比较好的还是基于 Java 一站式解决方案,也就是 spring。人家 spring 基本上承包了大部分我们需要使用的框架,spirng cloud 做微服务,spring boot 做脚手架,所以用 sping session 是一个很好的选择。
  • 给 sping session 配置基于 redis 来存储 session 数据,然后配置了一个 spring session 的过滤器,这样的话,session 相关操作都会交给 spring session 来管了。接着在代码中,就用原生的 session 操作,就是直接基于 spring sesion 从 redis 中获取数据了。
  • 下面是配置与代码示例:
    • 在 pom.xml 中配置:

      <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.2.1.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.1</version>
      </dependency>
      
    • 在 spring 配置文件中配置:

      <bean id="redisHttpSessionConfiguration"
           class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
          <property name="maxInactiveIntervalInSeconds" value="600"/>
      </bean>
      
      <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
          <property name="maxTotal" value="100" />
          <property name="maxIdle" value="10" />
      </bean>
      
      <bean id="jedisConnectionFactory"
            class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
          <property name="hostName" value="${redis_hostname}"/>
          <property name="port" value="${redis_port}"/>
          <property name="password" value="${redis_pwd}" />
          <property name="timeout" value="3000"/>
          <property name="usePool" value="true"/>
          <property name="poolConfig" ref="jedisPoolConfig"/>
      </bean>
      
    • 在 web.xml 中配置:

      <filter>
          <filter-name>springSessionRepositoryFilter</filter-name>
          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>springSessionRepositoryFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      
    • 示例代码:

      @RestController
      @RequestMapping("/test")
      public class TestController {
      
          @RequestMapping("/putIntoSession")
          public String putIntoSession(HttpServletRequest request, String username) {
              request.getSession().setAttribute("name",  "leo");
              return "ok";
          }
      
          @RequestMapping("/getFromSession")
          public String getFromSession(HttpServletRequest request, Model model){
              String name = request.getSession().getAttribute("name");
              return name;
          }
      }
      

2. 分布式事务方案

2.1 两阶段提交方案/XA方案

  • 所谓的 XA 方案,即:两阶段提交
  • 有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
  • 这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。
  • 其次,该方法现在很少用到,因为一般来说某个系统内部如果出现跨多个库的这么一个操作,是不合规的。如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。
    在这里插入图片描述

2.2 TCC 方案

  • TCC 的全称是:Try、Confirm、Cancel。

    • Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留
    • Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
    • Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
  • 这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大,非常之恶心。

  • 比如,一般来说跟钱相关的,跟钱打交道的,支付、交易相关的场景,会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。而且最好是你的各个业务执行的时间都比较短。

  • 但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码是很难维护的
    在这里插入图片描述

2.3 本地消息表

  • 这个大概意思是这样的:

    • A 系统在自己本地一个事务里操作同时,插入一条数据到消息表(业务表和消息表同时插入);
    • 接着 A 系统将这个消息发送到 MQ 中去;
    • B 系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,然后执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息;
    • B 系统执行成功之后,就会更新自己本地消息表的状态以及 A 系统消息表的状态;
    • 如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到 MQ 中去,让 B 再次处理;
  • 这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止。

  • 这个方案说实话最大的问题就在于严重依赖于数据库的消息表来管理事务啥的,如果是高并发场景咋办呢?咋扩展呢?所以一般确实很少用。
    在这里插入图片描述

2.4 可靠消息最终一致性方案

  • 这个的意思,就是干脆不要用本地的消息表了,直接基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。

  • 大概的流程就是:

    • A 系统发送一个HalfMsg到消息中间件。此时 B 系统无法立刻消费HalfMsg,只有当Commit了HalfMsg后, B 系统才能消费到这条消息。
    • A 系统执行本地事务。
    • 如果A 系统执行本地事务成功,就向消息中间件发送一个Commit消息,将HalfMsg的状态修改为【已提交】,然后通知 B 系统执行事务;
    • 如果A 系统执行本地事务失败,就向消息中间件发送一个Rollback消息,将 HalfMsg 的状态修改为【已取消】。
    • 并且消息中间件会定期去向 A 系统 询问,是否可以Commit或者Rollback那些由于错误没有被终结的HalfMsg,以此来结束它们的生命周期,以达成事务最终的一致。之所以需要这个询问机制,是因为A 系统 可能提交完本地事务,还没来得及对HalfMsg进行Commit或者Rollback,就挂掉了,这样就会处于一种不一致状态。
    • B 系统消费完消息后,可能因为自身异常,导致业务执行失败,此时就必须要能够重复消费消息。RocketMQ提供了ACK机制,即RocketMQ只有收到 B 系统 的ack message后才认为消费成功。所以, B 系统 可以在自身业务员逻辑执行成功后,向RocketMQ发送ack message,保证消费逻辑执行成功。

在这里插入图片描述

2.5 最大努力通知方案

  • 这个方案的大致意思就是:
    • 系统 A 本地事务执行完之后,发送个消息到 MQ;
    • 这里会有个专门消费 MQ 的最大努力通知服务,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口
    • 要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/553654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

极狐(GitLab) 重磅发布新产品「极狐星」,让研发效能看得清,算得准,成就企业精英效能管理

在研发驱动业务增长的今天&#xff0c;越来越多的研发管理者发现&#xff1a; 总是觉得研发资源不够用&#xff1f; 如何用数据衡量研发效能&#xff1f; 如何定位软件交付瓶颈&#xff1f; 怎样管理并预警项目状态&#xff1f; 想尽早发现代码泄露风险怎么办&#xff1f;…

GPS轨迹在Three.js中的地理对齐和显示

如何使用 three.js 可视化 GPS 轨迹&#xff1f; 棘手的部分是获得正确的投影&#xff0c;以便 GPS 轨迹与我的 Jotunheimen 地形图对齐。 在 D3.js 的帮助下&#xff0c;我能够做我想做的事。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 我将使用我之前在 Leaflet…

二十三种设计模式第八篇--装饰器模式

装饰器模式是一种结构型设计模式&#xff0c;它允许在不改变对象原有结构的情况下&#xff0c;动态地添加新的行为或功能。装饰器模式通过将对象包装在一个装饰器对象中&#xff0c;来实现对对象的功能扩展。装饰器对象与被装饰对象具有相同的接口&#xff0c;因此可以无缝地替…

ES6中数组新增了哪些扩展?

一、扩展运算符的应用 ES6通过扩展元素符...&#xff0c;好比 rest 参数的逆运算&#xff0c;将一个数组转为用逗号分隔的参数序列 console.log(...[1, 2, 3]) // 1 2 3console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5[...document.querySelectorAll(div)] // [<div>, …

线上品牌销售裂变,质变

大家好&#xff01; 我是小鱼经过前两期的 品牌线上运营分享 我们大概有了相对的概念 那么我们这期简单讲一下 如何让线上品牌销售产生 优质的变化。 分享 品牌方让“专业的人做专业的事”&#xff1a; 每个小程序店可招募1w个分享者负责引流和推广自家的视频号&#xff0c; 用…

MyBatis缓存机制要点解析以及如何与三方缓存组件Redis整合示例

文章目录 一、MyBatis的一级缓存1、每个SqlSession都有自己的一级缓存2、同一个SqlSession但是查询条件不同3、 同一个SqlSession两次查询期间执行了任何一次增删改操作 4、同一个SqlSession自己手动清空一级缓存二、MyBatis的二级缓存1、二级缓存的相关配置 三、一级\二级缓存…

外购设备PDA

专业扫描引擎&#xff0c;扫尽千军万码 工业级专业扫描引擎&#xff0c;数据采集精准、快速、安全&#xff1b; 同时增加摄像头扫描&#xff0c;自带绿点定位&#xff0c;实现快速对准&#xff1b; 可识别破损&#xff0c;沾染灰渍等条码提高工作效率。 一、产品特点 216GB/…

xhs xs _webmsxyw 纯算法还原盗用代码请注明出处搬来搬去真的很下头!

本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 最新版 x-s 没露任何版权请审核员认真对待谢谢。 【2023.05.22】 更新全站接口通用 …

携手企企通,农业产业化国家重点龙头企业「罗牛山」加速采购数智化建设

导语 与企企通形成战略合作&#xff0c;双方基于供应商、合同管理、采购协同等多方面的应用场景&#xff0c;打造立足海南辐射全国的行业标准化解决方案。行业案例的示范作用&#xff0c;不仅对牛罗山采购业务数字化有指导意义&#xff0c;对整个畜牧养殖行业加入采购供应链管…

redis-实现限流

1、 主流的四种限流策略&#xff0c;我都可以通过redis实现 引言 在web开发中功能是基石&#xff0c;除了功能以外运维和防护就是重头戏了。因为在网站运行期间可能会因为突然的访问量导致业务异常、也有可能遭受别人恶意攻击 所以我们的接口需要对流量进行限制。俗称的QPS也是…

finallshell mac SSH工具

一、FinallShell 是什么 FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 特色功能: 云端同步,免费海外服务器远程桌面加速,ssh加速,本地化命令输入框,支持自动补全,命令历史,自定义命令参数 二、主要特性 …

CMake Practice 学习笔记四---使用动静态库

任务&#xff1a; 编写一个程序使用我们上一届构建的共享库 1、准备工作 在/backup/cmake目录建立t4目录 mkdir t4在t4目录中建立src目录&#xff0c;并编写源文件main.c cd t4 mkdir src && cd src touch main.cmain.c的内容如下&#xff1a; #include <hel…

博客系统后端设计(七) - 实现显示用户信息与注销功能

文章目录 1. 显示用户信息1.1 约定前后端交互接口1.2 修改列表页的前段代码1.3 实现详情页的后端代码1.4 实现详情页的前端代码 2. 注销2.1 确定前后端交互接口2.2 实现后端代码2.3 修改前端代码 1. 显示用户信息 此处的用户名是写死的&#xff0c;我们希望的是此处是能够动态生…

nodejs+vue婚庆服务网站的设计与实现

为了适应现代人类强烈的时间观念&#xff0c;对于用户&#xff0c;因此&#xff0c;这就需要一个互联网平台实现在线婚庆服务网站&#xff0c;正是这么一个方便的平台。本网站中&#xff0c;用户与活动报名可以以最方便的形式&#xff0c;在最短的时间内获悉报名信息&#xff0…

Nginx Web页面缓存 Rsync远程同步

Nginx Web页面缓存 在http块中加配置&#xff1a; proxy_cache_path /data/nginx/cache levels1:2 keys_zonemy_cache:10m max_size10g inactive60m use_temp_pathoff ##################################### path&#xff1a;强制参数&#xff0c;指定缓存文件的存放路径 …

51单片机蓝牙APP自助商品售卖机12864投币找零

实践制作DIY- GC0132-蓝牙APP自助商品售卖机 一、功能说明&#xff1a; 基于51单片机设计-蓝牙APP自助商品售卖机 二、功能介绍&#xff1a; 硬件组成&#xff1a;STC89C52单片机最小系统LCD12864显示蜂鸣器ULN2003步进电机模拟出商品多个按键&#xff08;找零、确认、投…

掌握RDD算子

文章目录 一、准备本地系统文件二、把文件上传到HDFS三、启动HDFS服务四、启动Spark服务五、启动Spark Shell六、映射算子案例任务1、将rdd1每个元素翻倍得到rdd2任务2、将rdd1每个元素平方得到rdd2任务3、利用映射算子打印菱形IDEA里创建项目实现 七、过滤算子案例任务1、过滤…

编写 ROS 服务节点 Service 和 Client(python/C++)(六)

1.编写 Service 节点&#xff08;C&#xff09; 进入目录 cd ~/catkin_ws/src/beginner_tutorials/src然后vim server.cpp 复制代码粘贴&#xff0c;shiftinsert 粘贴 &#xff0c;然后按Esc 键&#xff0c;然后输入:wq 就可以保存退出了 #include "ros/ros.h" …

OSI分层

1 应用层 最上层的&#xff0c;也是我们能直接接触到的就是应用层&#xff08;Application Layer&#xff09;&#xff0c;我们电脑或手机使用的应用软件都是在应用层实现。那么&#xff0c;当两个不同设备的应用需要通信的时候&#xff0c;应用就把应用数据传给下一层&#x…

小航助学信息学奥赛C++ GoC模拟试卷(含题库答题软件账号)

信息学奥赛C GoC系统请点击 电子学会-全国青少年编程等级考试真题Scratch一级&#xff08;2019年3月&#xff09;在线答题_程序猿下山的博客-CSDN博客_小航答题助手 单选题10.0分 删除编辑 答案:C 第1题goc命令可以通过多命令拼接方式&#xff0c;优化代码布局&#xff0c;…