Redis分布式锁和分布式事务

这篇具有很好参考价值的文章主要介绍了Redis分布式锁和分布式事务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Redis分布式锁和分布式事务

一、Redis分布式锁
1.1 watch和事务实现分布式锁

原理是通过watch来观察一个变量,一个线程在操作的时候,其他线程会操作失败,相当于乐观锁。

1.2 setnx实现分布式锁

原理是通过setnx设置一个变量,设置成功的线程抢到锁,执行相关的业务,执行完毕,删除变量,相当于释放锁。没有设置成功的不执行业务操作。

1.3 Redission实现分布式锁

参考:https://www.cnblogs.com/qdhxhz/p/11046905.html

代码实现:https://blog.csdn.net/qq_46388795/article/details/107183662

二、Redis分布式事务
2.1、分布式事务的常见分类

分布式事务可以分成强一致性和最终一致性两种方案。对于强一致性,可以了解下「二阶段提交协议(2PC)」、「三阶段提交协议(3PC)」。但是,强一致性存在一些问题,因此生产环境中更多的是利用最终一致性的方案。

分布式事务有多种主流形态,包括:

  • 基于消息实现的分布式事务
  • 基于补偿实现的分布式事务
  • 基于TCC实现的分布式事务
  • 基于SAGA实现的分布式事务
  • 基于2PC、3PC实现的分布式事务
2.2 单机事务的选择

这个相信大家都很清楚,在条件允许的情况下,我们应该尽可能地使用单机事务,因为单机事务里,无需额外协调其他数据源,减少了网络交互时间消耗以及协调时所需的存储IO消耗,在修改等量业务数据的情况下,单机事务将会有更高的性能。

但单机数据库由于 业务逻辑解耦等因素进行了数据库垂直拆分、或者由于单机数据库性能压力等因素进行了数据库水平拆分之后,数据分布于多个数据库,这时若需要对多个数据库的数据进行协调变更,则需要引入分布式事务。

分布式事务的模式有很多种,那究竟要怎么选择适合业务的模式呢?以下我们将从使用场景、性能、开发成本这几个方面进行分析。

2.3 基于消息事务的选择

基于消息实现的事务适用于分布式事务的提交或回滚只取决于事务发起方的业务需求,其他数据源的数据变更跟随发起方进行的业务场景。

举个例子,假设存在业务规则:某笔订单成功后,为用户加一定的积分。

在这条规则里,管理订单数据源的服务为事务发起方,管理积分数据源的服务为事务跟随者。

从这个过程可以看到,基于消息队列实现的事务存在以下操作:

  • 订单服务创建订单,提交本地事务
  • 订单服务发布一条消息
  • 积分服务收到消息后加积分

我们可以看到它的整体流程是比较简单的,同时业务开发工作量也不大:

  • 编写订单服务里订单创建的逻辑
  • 编写积分服务里增加积分的逻辑

可以看到该事务形态过程简单,性能消耗小,发起方与跟随方之间的流量峰谷可以使用队列填平,同时业务开发工作量也基本与单机事务没有差别,都不需要编写反向的业务逻辑过程。因此基于消息队列实现的事务是我们除了单机事务外最优先考虑使用的形态。

2.3 基于补偿事务的选择

但是基于消息实现的事务并不能解决所有的业务场景,例如以下场景:某笔订单完成时,同时扣掉用户的现金。

这里事务发起方是管理订单库的服务,但对整个事务是否提交并不能只由订单服务决定,因为还要确保用户有足够的钱,才能完成这笔交易,而这个信息在管理现金的服务里。这里我们可以引入基于补偿实现的事务,其流程如下:

  • 创建订单数据,但暂不提交本地事务
  • 订单服务发送远程调用到现金服务,以扣除对应的金额
  • 上述步骤成功后提交订单库的事务

以上这个是正常成功的流程,异常流程需要回滚的话,将额外发送远程调用到现金服务以加上之前扣掉的金额。

以上流程比基于消息队列实现的事务的流程要复杂,同时开发的工作量也更多:

  • 编写订单服务里创建订单的逻辑
  • 编写现金服务里扣钱的逻辑
  • 编写现金服务里补偿返还的逻辑

可以看到,该事务流程相对于基于消息实现的分布式事务更为复杂,需要额外开发相关的业务回滚方法,也失去了服务间流量削峰填谷的功能。但其仅仅只比基于消息的事务复杂多一点,若不能使用基于消息队列的最终一致性事务,那么可以优先考虑使用基于补偿的事务形态。

(题外话:阿里GTS也是利用补偿实现,只不过补偿代码自动生成,无需业务干预,同时接管应用数据源,禁止业务修改处于全局事务状态中的记录。)

2.4 基于TCC事务的选择

然而基于补偿的事务形态也并非能实现所有的需求,如以下场景:某笔订单完成时,同时扣掉用户的现金,但交易未完成,也未被取消时,不能让客户看到钱变少了。

这时我们可以引入TCC,其流程如下:

  • 订单服务创建订单
  • 订单服务发送远程调用到现金服务,冻结客户的现金
  • 提交订单服务数据
  • 订单服务发送远程调用到现金服务,扣除客户冻结的现金

以上是正常完成的流程,若为异常流程,则需要发送远程调用请求到现金服务,撤销冻结的金额。

以上流程比基于补偿实现的事务的流程要复杂,同时开发的工作量也更多:

  • 订单服务编写创建订单的逻辑
  • 现金服务编写冻结现金的逻辑
  • 现金服务编写扣除现金的逻辑
  • 现金服务编写解冻现金的逻辑

TCC实际上是最为复杂的一种情况,其能处理所有的业务场景,但无论出于性能上的考虑,还是开发复杂度上的考虑,都应该尽量避免该类事务。

2.5 基于SAGA实现的事务选择

SAGA可以看做一个异步的、利用队列实现的补偿事务。

其适用于无需马上返回业务发起方最终状态的场景,例如:你的请求已提交,请稍后查询或留意通知 之类。

将上述补偿事务的场景用SAGA改写,其流程如下:

  • 订单服务创建最终状态未知的订单记录,并提交事务
  • 现金服务扣除所需的金额,并提交事务
  • 订单服务更新订单状态为成功,并提交事务

以上为成功的流程,若现金服务扣除金额失败,那么,最后一步订单服务将会更新订单状态为失败。

其业务编码工作量比补偿事务多一点,包括以下内容:

  • 订单服务创建初始订单的逻辑
  • 订单服务确认订单成功的逻辑
  • 订单服务确认订单失败的逻辑
  • 现金服务扣除现金的逻辑
  • 现金服务补偿返回现金的逻辑

但其相对于补偿事务形态有性能上的优势,所有的本地子事务执行过程中,都无需等待其调用的子事务执行,减少了加锁的时间,这在事务流程较多较长的业务中性能优势更为明显。同时,其利用队列进行进行通讯,具有削峰填谷的作用。

因此该形式适用于不需要同步返回发起方执行最终结果、可以进行补偿、对性能要求较高、不介意额外编码的业务场景。

但当然SAGA也可以进行稍微改造,变成与TCC类似、可以进行资源预留的形态。

2.6 2pc和3pc事务

2pc其适用于参与者较少,单个本地事务执行时间较少,并且参与者自身可用性很高的场景,否则,其很可能导致性能下降严重。例如:XA

具体参考:https://www.cnblogs.com/zcjcsl/p/7989792.html

2.7 总结

并非一种事务形态就能打遍天下

通过分析我们可以发现,并不存在一种事务形态能解决所有的问题,我们需要根据特定的业务场景选择合适的事务形态。甚至于有时需要混合多种事务形态才能更好的完成目标,如 上面提到的 订单、积分、钱包混合的场景:订单的成功与否需要依赖于钱包的余额,但不依赖于积分的多少,因此可以混合基于消息的事务形态以加积分 及 基于补偿的事务形态以确保扣钱成功,从而得到一个性能更好,编码量更少的形态。

然而目前很多框架都专注于某单一方面的事务形态,如TCC单独一个框架,可靠消息单独一个框架,SAGA单独一个框架,他们各自独立,容易导致以下问题:

  • 由于前期只采用了其中一种类型事务的框架,因为工具目前只有锤子,引入其他工具又涉及测试、阅读代码等过程,因此把所有问题都看做钉子,导致性能偏低或者实现不够优雅
  • 由于不同框架管理事务的形态可能不一致,导致不能很好的协调工作,如某一个TCC框架和另一个基于消息的事务框架无法很好融合。

解决方案

为了解决上面提到的问题,EasyTransaction这个基于Spring的分布式事务框架,实现了上述除2PC以外的所有事务形态,并提供了统一的使用接口,完美地解决了以上的问题。其主要特性如下:

  • 一个框架包含多种事务形态,一个框架搞定所有类型的事务
  • 多种事务形态可混合使用
  • 高性能,若不启用框架的幂等功能,对业务数据库的额外消耗仅为写入25字节的一行
  • 可选的框架幂等实现(包括调用次序错乱处理),大幅减轻业务开发工作量
  • 业务代码可实现完全无入侵
  • 支持嵌套事务
  • 无需额外部署协调者,不同APP的服务协调自身发起的事务
  • 分布式事务ID可关联业务ID,业务类型,APPID,便于监控各个业务的分布式事务执行情况

若各位对ET兴趣,可以到 https://github.com/QNJR-GROUP/EasyTransaction 查看详细介绍及示例,本文不再深入介绍

总结

不同业务场景应按需引入不同的事务形态,在条件允许的情况下,个人建议按照如下次序选择对应的事务形态:

单机事务》基于消息的事务》基于补偿的事务》TCC事务

因SAGA事务的形态需要配合较为明显的前端业务交互变更,个人建议在单一事务执行过程较长、存在较多子事务,并且无法使用基于消息的事务形态时使用。

2.8 具体应用

使用阿里的seata框架:

参考:http://seata.io/zh-cn/docs/overview/what-is-seata.html

https://blog.csdn.net/qq_35721287/article/details/108982806文章来源地址https://www.toymoban.com/news/detail-494621.html

到了这里,关于Redis分布式锁和分布式事务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RocketMQ分布式事务 -> 最终一致性实现

    · 分布式事务的问题常在业务与面试中被提及, 近日摸鱼看到这篇文章, 阐述的非常通俗易懂, 固持久化下来我博客中, 也以便于我二刷 转载源 : 基于RocketMQ分布式事务 - 完整示例 本文代码不只是简单的demo,考虑到一些异常情况、幂等性消费和死信队列等情况,尽量向可靠业务

    2024年02月15日
    浏览(56)
  • SpringCloudAlibaba集成RocketMQ实现分布式事务事例(一)

    业务需求 用户请求订单微服务 order-service 接口删除订单(退货),删除订单时需要调用 account-service的方法给账户增加余额,一个典型的分布式事务问题。 代码实现 事务消息有三种状态: TransactionStatus.CommitTransaction:提交事务消息,消费者可以消费此消息 TransactionStatus.Roll

    2024年02月13日
    浏览(106)
  • (快手一面)分布式系统是什么?为什么要分布式系统?分布式环境下会有哪些问题?分布式系统是如何实现事务的?

    《分布式系统原理与泛型》中这么定义分布式系统: “ 分布式系统是若干独立计算机的集合, 这些计算机对于用户来说就像单个相关系统 ”, 分布式系统(distributed system)是建立在网络之上的软件系统。 就比如:用户在使用京东这个分布式系统的时候,会感觉是在使用一

    2024年02月08日
    浏览(70)
  • Spring Boot实现分布式事务的协调和管理

    在现代的分布式系统中,往往存在多个服务协同完成一个业务操作的情况。而在这种情况下,如何保证所有服务的数据一致性成为了一个重要的问题。Spring Boot作为一个流行的Java开发框架,提供了多种方法来实现分布式事务的协调和管理。本文将介绍一些常用的方式和技术来

    2024年02月08日
    浏览(41)
  • JAVA微服务分布式事务的几种实现方式

    一致性(Consistency) :在分布式系统中所有的数据备份,在同一时刻都保持一致状态,如无法保证状态一致,直接返回错误; 可用性(Availability):在集群中一部分节点故障,也能保证客户端访问系统并得到正确响应,允许一定时间内数据状态不一致; 分区容错性(Partiti

    2024年02月12日
    浏览(51)
  • 一个注解解决分布式锁和接口幂等性,springboot 实战 。强到离大谱

    如今基本上都是分布式、多节点时代,我们业务代码中避免不了需要使用分布式锁。 admin4j-lock 为我们提供分布式锁解决方案。支持 redisson 和 zookeeper 分布式锁 支持redisson分布式锁和zookeeper 分布式锁 支持可重入锁 支持读写锁 支持红锁 redLock 支持一个注解解决分布式锁问题

    2023年04月26日
    浏览(44)
  • 分布式系统的多数据库,实现分布式事务回滚(1.7.0 seata整合2.0.4nacos)

    1、解决的应用场景是分布式事务,每个服务有独立的数据库。 2、例如:A服务的数据库是A1,B服务的数据库是B2,A服务通过feign接口调用B服务,B涉及提交数据到B2,业务是在B提交数据之后,在A服务内报错。 所以,希望B能回滚事务。这就是跨库的数据回滚 seata下载地址 注意

    2024年02月11日
    浏览(43)
  • springboot dubbo seata nacos集成 分布式事务seata实现

    官网:http://seata.io/zh-cn/docs/overview/what-is-seata.html Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。 官网;https://cn.dubbo.apache.org/zh-cn/overview/what/

    2024年02月13日
    浏览(47)
  • 分布式锁实现(mysql,以及redis)以及分布式的概念

    我旁边的一位老哥跟我说,你知道分布式是是用来干什么的嘛?一句话给我干懵了,我能隐含知道,大概是用来做分压处理的,并增加系统稳定性的。但是具体如何,我却道不出个1,2,3。现在就将这些做一个详细的总结。至少以后碰到面试官可以说上个123。 那么就正式进入

    2024年01月21日
    浏览(61)
  • Redis——》实现分布式锁

    推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结——》【SpringBoot】     总结——》【MyBatis、MyBatis-Plus】     总结——》【Linux】     总结——》【MongoDB】    

    2024年02月10日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包