掌握分布式事务锁,这个大厂实战订单锁你一定要会

分布式趋势

目前几乎很多大型网站及应用都是分布式部署的,分布式场景中我们也都会遇到一个非常重要的问题:数据一致性。正如分布式的CAP理论说的一样:“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者进行取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支撑,比如分布式事务、分布式锁、定时任务调度等。尽管Java提供了很多并发处理API,但这些API在分布式场景中就显得无能为力了。

所以针对分布式锁的实现我们需要借助别的工具,目前比较常用的有以下几种方案:

  1. 基于数据库实现分布式锁
  2. 基于缓存(redis,memcached,tair)实现分布式锁
  3. 基于Zookeeper实现分布式锁

本篇发文我们主要说下基于Redis的分布式锁实战。

实际编写代码之前,我们说下首要条件

分布式锁可用的四个条件:

  1. 互斥性。在任意时刻,只有一个客户端能持有锁。
  2. 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  3. 具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
  4. 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

分布式锁实战步骤:

编写ILock接口

编写ILock接口实现

LockGetter抽象类

从图示我们可以看出,通过LockGetter抽象类进行具体的加锁成功或则失败的具体业务走向。这一个思想同学们要谨记于心。能够熟练应用的话,他会使你在编程之路上走的更加顺畅。

此外,可以看到,我们实际加锁就一行代码:jedis.set(fieldKey, value, "NX", "EX", seconds);,这个set()方法一共有五个形参:

第一个参数为key,我们使用key来当锁,因为key是唯一的。

第二个参数为value,我们传的是requestId,很多童鞋可能不明白,有key作为锁不就够了吗,为什么还要用到value?原因就是我们在上面讲到可靠性时,分布式锁要满足第四个条件解铃还须系铃人,通过给value赋值为requestId,我们就知道这把锁是哪个请求加的了,在解锁的时候就可以有依据。requestId可以使用UUID.randomUUID().toString()方法生成。

第三个参数为nxxx,这个参数我们填的是NX,意思是SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;

第四个参数为expx,这个参数我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。

第五个参数为time,与第四个参数相呼应,代表key的过期时间。

总的来说,执行上面的set()方法之后会出现两种情况:

  1. 当前没有锁(key不存在),那么就进行加锁操作,并对锁设置个有效期,同时value表示加锁的客户端。
  2. 锁已经存在,redis不做任何操作。

总结:

使用缓存来实现分布式锁优点:

  1. 可以提供更好的性能,同时很多缓存服务都是集群部署的,可以避免单点问题。
  2. 很多缓存服务都提供了可以用来实现分布式锁的方法,比如redis的setnx方法等。
  3. 缓存服务也都提供了对数据的过期自动删除的支持,可以直接设置超时时间来控制锁的释放。

使用缓存实现分布式锁尽管性能好,实现起来较为方便。但也不是没有缺点,有时候我们的程序内部出现异常后可能会发生死锁,这就需要开发时候注意代码编写,后续测试人员测试时候测试案例要尽可能覆盖。

原文地址:https://blog.51cto.com/14409778/2411256

时间: 2024-11-05 23:23:30

掌握分布式事务锁,这个大厂实战订单锁你一定要会的相关文章

分布式事务以及锁

标题格 1.非公平锁 2.TCC分布式事务原理 1.非公平锁 在加锁过程,线程1运行,线程2处于等待队列. 线程1运行结束,结果线程3抢先于线程2进行.这就是非公平锁的简单含义. 在ReentrantLock lock = new ReentrantLock()默认的就是非公平锁,构造函数中加入true:ReentrantLock lock = new ReentrantLock(true). 公平锁原则就是线程3就绪后,会先查看等待队列是否有线程,有就排队. 2.TCC分布式事务原理 使用sp

浅谈分布式事务与TX-LCN

最近做项目使用到了分布式事务,下面这篇文章将给大家介绍一下对分布式事务的一些见解,并讲解分布式事务处理框架TX-LCN的执行原理,初学入门,错误之处望各位不吝指正. 什么情况下需要使用分布式事务? 使用的场景很多,先举一个常见的:在微服务系统中,如果一个业务需要使用到不同的微服务,并且不同的微服务对应不同的数据库. 打个比方:电商平台有一个客户下订单的业务逻辑,这个业务逻辑涉及到两个微服务,一个是库存服务(库存减一),另一个是订单服务(订单数加一),示意图如下: 如果在执行这个业务逻辑时没有使用

【故障处理】分布式事务ORA-01591错误解决

[故障处理]分布式事务ORA-01591错误解决 1  BLOG文档结构图       2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 分布式事务的简单概念         ② ORA-01591错误解决   Tips: ① 本文在ITpub(http://blog.itpub.net/26736162).博客园(http://www.cnblogs.com/lhrbest)和微信公众号(x

Percolator:基于BigTable的分布式事务实现

Google为了解决网页索引的增量处理,以及维护数据表和索引表的一致性问题,基于BigTable实现了一个支持分布式事务的存储系统.这里重点讨论这个系统的分布式事务实现,不讨论percolator中为了支持增量计算而实现的Notifications机制. 该系统基于BigTable,支持snapshot isolation隔离级别,这个隔离级别不在ANSI定义的隔离级别范围内.简单来说,就是一个事务看到的是一个stable的数据库的快照.快照隔离相对于可串行化隔离级别的优点是更高的读性能,不需要

蚂蚁技术专家:一篇文章带你学习分布式事务

小蚂蚁说: 分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构中都会涉及到的一个东西,特别是在这几年越来越火的微服务架构中,几乎可以说是无法避免,本文就围绕分布式事务各方面与大家进行介绍. 一. 事务 1.1 什么是事务 数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 事务拥有以下四个特性,习惯上被称为ACID特性: 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要

分布式事务框架-seata初识

摘自:https://www.cnblogs.com/iceggboom/p/12144570.html 分布式事务框架-seata初识 一.事务与分布式事务 事务,在数据库中指的是操作数据库的最小单位,往大了看,事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消. 那为什么会有分布式事务呢?单机事务是通过将操作限制在一个会话内通过数据库本身的锁以及日志来实现ACID.因为引入了分布式架构,所以事务的参与者.支持事务的服务器.资源服务器以及事务管理器

大厂面试必知必会:图解分布式事务实现原理

问题场景 什么是事务? 事务是数据库从一个稳定状态变迁到另一个稳定状态的保证,具备 ACID 这 4 个特性: 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节.事务在执行过程中发生错误,会被回滚到事务开始前的状态. 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性限制没有被破坏. 隔离性(Isolation):两个事务的执行是互不干扰的,两个事务时间不会互相影响. 持久性(Durability):在事务完成以

springCloud分布式事务实战(六)编写第二个微服务

(1)创建工程 (2)添加 jar pom.xml添加:springboot 父, mysql连接,(mybatis, spring-mybatis springboot ,阿里连接池) ,服务中心客户端. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="

JTA分布式事务实战

spring3.0    分布式事务  jta  atomikos 1.使用如下jar包 atomikos-util.3.7.0.jar cglib-nodep-2.2.2.jar transactions-3.7.0.jar transactions-api-3.7.0.jar transactions-jdbc-3.7.0.jar transactions-jta-3.7.0.jar 2.spring配置文件如下: Xml代码   <?xml version="1.0" en