精华内容
下载资源
问答
  • 分布式事务锁

    千次阅读 2019-02-11 17:20:45
    在单机时代,虽然不需要分布式锁,但也面临过类似的问题,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制,即当某个线程获取到这个资源后,就立即对这个资源进行...

    背景(转):

     

    在单机时代,虽然不需要分布式锁,但也面临过类似的问题,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制,即当某个线程获取到这个资源后,就立即对这个资源进行加锁,当使用完资源之后,再解锁,其它线程就可以接着使用了。例如,在JAVA中,甚至专门提供了一些处理锁机制的一些API(synchronize/Lock等)。

    但是到了分布式系统的时代,这种线程之间的锁机制,就没作用了,系统可能会有多份并且部署在不同的机器上,这些资源已经不是在线程之间共享了,而是属于进程之间共享的资源。

    因此,为了解决这个问题,我们就必须引入「分布式锁」。

    分布式锁,是指在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问。

    分布式锁要满足哪些要求呢?

    排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取

    避免死锁:这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)

    高可用:获取或释放锁的机制必须高可用且性能佳

    讲完了背景和理论,那我们接下来再看一下分布式锁的具体分类和实际运用。

     

    分布式事务锁的三种方式:

    1、基于数据库实现

    2、基于Redis实现

    3、基于ZooKeeper实现

     

    基于数据库实现

      基于数据库的乐观锁

      乐观锁机制其实就是在数据库表中引入一个版本号(version)字段来实现的。

      当我们要从数据库中读取数据的时候,同时把这个version字段也读出来,如果要对读出来的数据进行更新后写回数据库,则需要将version加1,同时将新的数据与新的version更新到数据表中,且必须在更新的时候同时检查目前数据库里version值是不是之前的那个version,如果是,则正常更新。如果不是,则更新失败,说明在这个过程中有其它的进程去更新过数据了。

     

    基于redis实现

    1、选用Redis实现分布式锁原因:

    (1)Redis有很高的性能; 
    (2)Redis命令对此支持较好,实现起来比较方便

    2、使用命令介绍:

    (1)SETNX

    SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。

    (2)expire

    expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。

    (3)delete

    delete key:删除key

    在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。
     

    基于ZooKeeper实现

      

    ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下:

    (1)创建一个目录mylock; 
    (2)线程A想获取锁就在mylock目录下创建临时顺序节点; 
    (3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁; 
    (4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点; 
    (5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

     

    展开全文
  • Redis~分布式事务和分布式事务锁

    千次阅读 2020-12-24 14:06:28
    文章目录前话讲分布式事务锁前的几个概念Redis分布式事务锁原理核心思想问题一问题一问题三 前话 大家都知道redis是一个可以高速运行在缓存级别的数据库, 他的高速原因主要有几个原因 绝大部分请求是纯粹的内存...

    前话

    • 大家都知道redis是一个可以高速运行在缓存级别的数据库, 他的高速原因主要有几个原因
    1. 绝大部分请求是纯粹的内存操作(非常快速),避免了与硬盘的接触
    2. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
    3. 使用大量的hash思想的k v键值对, 获取效率为O(1)
    4. 依靠非阻塞的IO多路复用原则,使redis形成单线程去执行命令的服务器, 避免了不必要的阻塞和上下文切换和竞争条件

    redis采用IO复用实现单线程的方式, 将命令任务分装在队列中让一个线程去串行化执行, 自然避免了线程安全问题, 这也是为什么我们常说redis是基于原子操作的原因

    跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源.而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳

    总结Redis特点

    redis快是因为他是基于内存进行操作的,并且使用了大量的kv数据结构和很多特殊的数据类型,还使用了io多路复用避免了阻塞,所以使用多线程就可以避免上下文切换和锁机制和线程的创建和销毁,而且说他是单线程但是其他操作比如持久化,连接管理都是多线程式的,最主要的是由于上述条件,redis的性能瓶颈不在线程上,而是在内存容量和网络带宽上

    • 但是还有一个问题, 上面说redis是单线程的, 那么就不会有线程安全问题, 那为什么还有让redis支持事务, 还要 要求他使用redis分布式事务锁

    没错,大家所熟知的 Redis 确实是单线程模型,指的是执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程的

    比如socket连接, 这就是一个多线程式的
    在redis事务中或有一个watch乐观锁去监视者数据是否被改动, 如果真的是完全单线程, 那么就不需要有这个监视的存在
    本质原因就是redis的socket连接是多线程的, 我们在开始redis事务, 往里面添加命令其实并没有真正的执行这些命令, 所以需要watch的监视, 防止其他socket连接进行了数据的操作
    下面看看redis的真实运行环境

    在这里插入图片描述

    • 它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。
      因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
    • 所以Redis 不仅仅是单线程, 他需要事务的支持, 就是因为多客户端对Redis的连接并不存在竞争关系。
    • 所以在单机服务器,出现资源的竞争,一般使用synchronized 还可以使用前的redis的事务就可以解决,但是在分布式的服务器上,多个系统或者说多个节点同时访问你这个redis节点,synchronized 和redis事务就无法解决这个问题,这就需要一个分布式事务锁

    讲分布式事务锁前的几个概念

    • 分布式:简单来说就是将业务进行拆分,部署到不同的机器来协调处理。比如用户在网上买东西,大致分为:订单系统、库存系统、支付系统、、、、这些系统共同来完成用户买东西这个业务操作。
    • 集群:同一个业务,通过部署多个实例来完成,保证应用的高可用,如果其中某个实例挂了,业务仍然可以正常进行,通常集群和分布式配合使用。来保证系统的高可用、高性能。
    • 分布式事务:按照传统的系统架构,下单、扣库存等等,都是在单机系统中, 这一系列的操作都是一个数据库中完成的,也就是说保证了事务的ACID特性。如果在分布式应用中就会涉及到跨应用、跨库。这样就涉及到了分布式事务,就要考虑怎么保证这一系列的操作要么都成功要么都失败。保证数据的一致性。
    • 分布式锁:因为资源有限,要通过互斥来保持一致性,比如下订单的数据库操作和支付的数据库操作就是一个保证互斥性, 不能同时去执行, 不然那就会出现一旦支付出现失败, 那么下订单也得重新下订单, 这就不合理了, 所以引入分布式事务锁。

    Redis分布式事务锁原理

    • 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
    • 简单来说就是好几个节点访问一个资源, 那我就是使用额外的锁机制互斥的只让其中一个能进行访问

    核心思想

    • 在被保护的redis节点加一把锁, 让这把锁和被保护的redis节建立直接映射
    • 在访问这个redis之前都去看看这把锁在不在
    • 如果不存在锁,说明没有客户端使用,可以执行任务,执行完毕,解锁,删除锁 (并且要保证判断有无锁和加锁是原子操作)
    • 如果锁从在则认为有其他客户端在使用,等待锁消失
      在这里插入图片描述
    • Redis中可以使用SETNX命令实现分布式锁,(因redis执行命令是单线程所以这个命令是院子的, 完全可以放心去使用)。
    • SETNX——SET if Not eXists(如果不存在,则设置):
    setnx key value
    
    • 如果需要解锁,使用 del key 命令就能释放锁

    问题一

    • 当一个客户端上锁之后服务宕机,由于锁是他上的只有他可以进行redis访问的,别人无法访问,所以导致锁无法被删除.

    解决思路

    • 给锁设置一个过期时间,可以通过两种方法实现:通过命令 “setnx 键名 过期时间 “;或者通过设置锁的expire(失效)时间,让Redis去删除锁。

    问题一

    • 当一个客户端设置了锁的失效时间, 但是这个客户端并没有宕机, 只是真的需要那么多时间来进行操作
    • 也就是任务执行过长,超过过期时间。

    解决思路
    这就是上图那个看门狗的作用可, 这条狗看到时间快到了, 就大喊一声让时间倒流~

    • 实际是通过客户端的一个守护线程,大概时间快到的时间给线程续命.

    问题三

    • 任务执行造成死循环,会造成无限续命

    解决思路
    设置最大续命时间, 或者设置最大续命次数

    展开全文
  • 我们在单机服务器,出现资源的竞争,一般使用synchronized 就可以解决,但是在分布式的服务器上,synchronized 就无法解决这个问题,这就需要一个分布式事务锁。 除此之外面试,基本会问springboot、Redis,然后都会...

    我们在单机服务器,出现资源的竞争,一般使用synchronized 就可以解决,但是在分布式的服务器上,synchronized 就无法解决这个问题,这就需要一个分布式事务锁。

    除此之外面试,基本会问springboot、Redis,然后都会一路再聊到分布式事务、分布式事务锁的实现。

    1、常见的分布式事务锁

    1、数据库级别的锁

    • 乐观锁,基于加入版本号实现
    • 悲观锁,基于数据库的 for update 实现

    2、Redis ,基于 SETNX、EXPIRE 实现

    3、Zookeeper,基于InterProcessMutex 实现

    4、Redisson,lcok、tryLock(背后原理也是Redis)

    本文主要介绍一下Redis和Redisson的分布式事务锁的原理。

    2、Redis 搭建模式

    Redis 的搭建方式:

    • 单机
    • 主从
    • 哨兵
    • 集群

    单机,只要一台Redis服务器,挂了就无法工作了

    主从,是备份关系, 数据也会同步到从库,还可以读写分离

    哨兵:master挂了,哨兵就行选举,选出新的master,作用是监控主从,主从切换

    集群:高可用,分散请求。目的是将数据分片存储,节省内存。

    单机:

    单机模式

    主从:

    主从模式

    哨兵:

    哨兵模式

    集群:

    集群模式

    3、几个概念

    分布式:简单来说就是将业务进行拆分,部署到不同的机器来协调处理。比如用户在网上买东西,大致分为:订单系统、库存系统、支付系统、、、、这些系统共同来完成用户买东西这个业务操作。

    集群:同一个业务,通过部署多个实例来完成,保证应用的高可用,如果其中某个实例挂了,业务仍然可以正常进行,通常集群和分布式配合使用。来保证系统的高可用、高性能。

    分布式事务:按照传统的系统架构,下单、扣库存等等,这一系列的操作都是一在一个应用一个数据库中完成的,也就是说保证了事务的ACID特性。如果在分布式应用中就会涉及到跨应用、跨库。这样就涉及到了分布式事务,就要考虑怎么保证这一系列的操作要么都成功要么都失败。保证数据的一致性。

    **分布式锁:**因为资源有限,要通过互斥来保持一致性,引入分布式事务锁。

    4、Redis分布式锁原理

    简单的来说,其实现原理如下:

    • 互斥性

      • 保证同一时间只有一个客户端可以拿到锁。
    • 安全性

      • 只有加锁的服务才能有解锁权限,也就是不能让客户端A加的锁,客户端B、C 都可以解锁。
    • 避免死锁

    • 保证加锁与解锁操作是原子性操作

      • 这个其实属于是实现分布式锁的问题,假设a用redis实现分布式锁
      • 假设加锁操作,操作步骤分为两步:1,设置key set(key,value) 2,给key设置过期时间
      • 假设现在a刚实现set后,程序崩了就导致了没给key设置过期时间就导致key一直存在就发生了死锁。

    讲了这么多,Redis实现分布式锁的核心就是:

    加锁:

    SET key value NX EX timeOut
    

    参数解释:

    NX:只有这个key不存才的时候才会进行操作,即 if not exists;
    EX:设置key的过期时间为秒,具体时间由第5个参数决定
    timeOut:设置过期时间保证不会出现死锁【避免宕机死锁】

    代码实现:

     public Boolean lock(String key,String value,Long timeOut){
         String var1 = jedis.set(key,value,"NX","EX",timeOut); //加锁,设置超时时间 原子性操作
         if(LOCK_SUCCESS.equals(var1)){
             return true;
         }
         return false;
     }
    

    总的来说,执行上面的set()方法就只会导致两种结果:

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

    注:从2.6.12版本后, 就可以使用set来获取锁、Lua 脚本来释放锁。setnx是以前刚开始的实现方式,set命令nx、xx等参数,,就是为了实现 setnx 的功能。

    解锁:

    代码实现:

    public Boolean redisUnLock(String key, String value) {
        String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else  return 0 end";
    
        Object var2 = jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
        if (UNLOCK_SUCCESS == var2) {
            return true;
        }
        return false;
    }
    

    这段lua代码的意思:首先获取锁对应的value值,检查是否与输入的value相等,如果相等则删除锁(解锁)。

    上面加锁、解锁,看着是挺麻烦的,所以就出现了Redisson。

    5、Redisson 分布式锁原理

    官方介绍:

    Redisson是一个在Redis的基础上实现的Java驻内存数据网格。

    就是在Redis的基础上封装了很多功能,以便于我们更方便的使用。

    只需要三行代码:

    RLock lock = redisson.getLock("myLock");
    lock.lock(); //加锁
    lock.unlock(); //解锁
    

    (1)加锁机制

    加锁流程:

    redisson的lock过程

    redisson的lock()、tryLock()方法 底层 其实是发送一段lua脚本到一台服务器:

    if (redis.call('exists' KEYS[1]) == 0) then  +  --  exists 判断key是否存在
           redis.call('hset' KEYS[1] ARGV[2] 1);  +   --如果不存在,hset存哈希表
           redis.call('pexpire' KEYS[1] ARGV[1]);  + --设置过期时间
           return nil;  +                            -- 返回null 就是加锁成功
              end;  +
              if (redis.call('hexists' KEYS[1] ARGV[2]) == 1) then  + -- 如果key存在,查看哈希表中是否存在(当前线程)
                  redis.call('hincrby' KEYS[1] ARGV[2] 1);  + -- 给哈希中的key加1,代表重入1次,以此类推
                  redis.call('pexpire' KEYS[1] ARGV[1]);  + -- 重设过期时间
                  return nil;  +
              end;  +
              return redis.call('pttl' KEYS[1]); --如果前面的if都没进去,说明ARGV[2]的值不同,也就是不是同一线程的锁,这时候直接返回该锁的过期时间
    
    

    参数解释:

    KEYS[1]:即加锁的key,RLock lock = redisson.getLock("myLock"); 中的myLock

    ARGV[1]:即 TimeOut 锁key的默认生存时间,默认30秒

    **ARGV[2]:**代表的是加锁的客户端的ID,类似于这样的:99ead457-bd16-4ec0-81b6-9b7c73546469:1

    其中lock()默认是30秒的生存时间。

    (2)锁互斥

    假如客户端A已经拿到了 myLock,现在 有一客户端(未知) 想进入:

    1、第一个if判断会执行“exists myLock”,发现myLock这个锁key已经存在了。
    2、第二个if判断,判断一下,myLock锁key的hash数据结构中, 如果是客户端A重新请求,证明当前是同一个客户端同一个线程重新进入,所以可从入标志+1,重新刷新生存时间(可重入); 否则进入下一个if。
    3、第三个if判断,客户端B 会获取到pttl myLock返回的一个数字,这个数字代表了myLock这个锁key的剩余生存时间。比如还剩15000毫秒的生存时间。

    此时客户端B会进入一个while循环,不停的尝试加锁。

    (3)watch dog 看门狗自动延期机制

    官方介绍:

    lockWatchdogTimeout(监控锁的看门狗超时,单位:毫秒)

    默认值:30000

    监控锁的看门狗超时时间单位为毫秒。该参数只适用于分布式锁的加锁请求中未明确使用leaseTimeout参数的情况。(如果设置了leaseTimeout那就会自动失效了呀~)

    看门狗的时间可以自定义设置:

    config.setLockWatchdogTimeout(30000);
    

    看门狗有什么用呢?

    假如客户端A在超时时间内还没执行完毕怎么办呢? redisson于是提供了这个看门狗,如果还没执行完毕,监听到这个客户端A的线程还持有锁,就去续期,默认是 LockWatchdogTimeout/ 3 即 10 秒监听一次,如果还持有,就不断的延长锁的有效期(重新给锁设置过期时间,30s)

    可以在lock的参数里面指定:

    lock.lock(); //如果不设置,默认的生存时间是30s,启动看门狗 
    lock.lock(10, TimeUnit.SECONDS);//10秒以后自动解锁,不启动看门狗,锁到期不续
    

    如果是使用了可重入锁( leaseTimeout):

    lock.tryLock(); //如果不设置,默认的生存时间是30s,启动看门狗 
    lock.tryLock(100, 10, TimeUnit.SECONDS);//尝试加锁最多等待100秒,上锁以后10秒自动解锁,不启动看门狗
    

    这里的第二个参数leaseTimeout 设置为 10 就会覆盖 看门狗的设置(看门狗无效),在10秒后锁就自动失效,不会去续期;如果是 -1 ,就表示 使用看门狗的默认值。

    (4)释放锁机制

    lock.unlock(),就可以释放分布式锁。就是每次都对myLock数据结构中的那个加锁次数减1。

    如果发现加锁次数是0了,说明这个客户端已经不再持有锁了,此时就会用:“del myLock”命令,从redis里删除这个key。

    为了安全,会先校验是否持有锁再释放,防止

    • 业务执行还没执行完,锁到期了。(此时没占用锁,再unlock就会报错)
    • 主线程异常退出、或者假死
    finally {
                if (rLock.isLocked()) {
                    if (rLock.isHeldByCurrentThread()) {
                        rLock.unlock();
                    }
                }
            }
    

    (5) 缺点

    如果是 主从、哨兵模式,当客户端A 把 myLock这个锁 keyvalue写入了 master,此时会异步复制给slave实例。

    万一在这个主从复制的过程中 master 宕机了,主备切换,slave 变成了master

    那么这个时候 slave还没来得及加锁,此时 客户端A的myLock的 值是没有的,客户端B在请求时,myLock却成功为自己加了锁。这时候分布式锁就失效了,就会导致数据有问题。

    所以说Redis分布式说最大的缺点就是宕机导致多个客户端加锁,导致脏数据,不过这种几率还是很小的。


    参考:

    • https://www.cnblogs.com/demingblog/p/10295236.html
    • http://www.voidcc.com/redisson/redisson-single-sentinel-mode-configuration
    • https://juejin.im/post/6844903874675867656

    ock`却成功为自己加了锁。这时候分布式锁就失效了,就会导致数据有问题。

    所以说Redis分布式说最大的缺点就是宕机导致多个客户端加锁,导致脏数据,不过这种几率还是很小的。


    参考:

    • https://www.cnblogs.com/demingblog/p/10295236.html
    • http://www.voidcc.com/redisson/redisson-single-sentinel-mode-configuration
    • https://juejin.im/post/6844903874675867656
    展开全文
  • 系统分布式锁的用法公司框架新增功能分布式锁的性能之王:缓存 > Zookeeper >= 数据库的实现实现原理:核心采用StackExchange.Redis的LockT...

    系统分布式锁的用法

    公司框架新增功能分布式锁:

    锁的性能之王:缓存 > Zookeeper >= 数据库

    锁的实现

    实现原理:核心采用StackExchange.Redis的LockTake方法实现。
    支持同步获取锁,或者等待直到超时获取锁。

    /// <summary>
        /// 分布式锁,提供全局分布式锁支持,以resource redis为基础
        /// 这个锁只能通过RpcContext来获取,通过自己手动释放
        /// </summary>
        public sealed class DistributedLock
        {
            private static readonly TimeSpan DefaultAbandonmentCheckFrequency = TimeSpan.FromSeconds(2);
    
            public readonly string lockName;
            private readonly string lockValue;
            private readonly int  checkTimeSpan = 50; //ms
            private readonly int autoDelete;
    
            private DistributedLock()
            {
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="lockName"></param>
            /// <param name="autoDelete">自动删除,ms,默认 60s</param>
            /// <param name="checkTimeSpan">如果不能获取锁,重复检查间隔:默认 50ms</param>
            internal DistributedLock(string lockName, int autoDelete = 60000,int checkTimeSpan = 50)
            {
                // note that just Global\ is not a valid name
                if (string.IsNullOrEmpty(lockName))
                    throw new ArgumentNullException("lockName不能为空");
    
                if (null == ResourceCache.Instance)
                    throw new Exception(@"ResourceCache 没有配置或无法连接");
    
                this.checkTimeSpan = Math.Max(checkTimeSpan,1);
                this.autoDelete = Math.Max(autoDelete,1);
                this.lockName = lockName;
                this.lockValue = lockName;
            }
    
           
            /// <summary>
            /// 获取锁
            /// </summary>
            /// <param name="timeout">超时为null,则尝试一次即返回</param>
            /// <returns>获取锁成功?</returns>
            internal bool Acquire(TimeSpan? timeout = null)
            {
                bool bLock = false;
                var dtStart = DateTime.Now.Ticks;
                while (!bLock)
                {
                    bLock = TryAcquireOnce();
                    if (timeout == null)
                    {
                        break;
                    }
                    if (!bLock)
                    {
                        Thread.Sleep(this.checkTimeSpan);
                    }
    
                    var ts = new TimeSpan(DateTime.Now.Ticks - dtStart);
                    if (ts >= timeout)
                    {
                        break;
                    }
                }
    
                return bLock;
            }
            //此处采用框架上下文管理分布式事务锁的释放,代码略。
            //public void Dispose()
            //{
            //    LockManager.ReleaseLock(this);
            //}
    
            internal void Release()
            {
                try
                {
                    var bRtn = ResourceCache.Instance.LockRelease(this.lockName, this.lockValue);
                    Trace.WriteLine($"释放锁 {this.lockName}:{bRtn}");
                }
                catch (Exception e)
                {
                    LogTextWriter.Write($"释放锁失败,系统自动超时释放:{this.lockName}");
                }
            }
    
            /// <summary>
            /// 释放锁
            /// </summary>
            public void ReleaseLock()
            {
                LockManager.ReleaseLock(this);
            }
    
            private bool TryAcquireOnce()
            {
                try
                {
                    Trace.WriteLine($"{Thread.CurrentThread.ManagedThreadId}:TryAcquireOnce");
                    var @lock = ResourceCache.Instance.LockTake(this.lockName, this.lockValue, new TimeSpan(0, 0, 0, 0, this.autoDelete));
                    return @lock;
                }
                catch (Exception e)
                {
                    return false;
                }
            }
    
        }
    

    锁的使用

    在当前上下文中获取一个分布式锁,第一个获取锁的将执行依赖当前key(一般为业务主键)的完整业务流程(包括多个微服务之间的调用和数据库的访问;

    后来者将无法获取锁,根据返回的结果来判断是否进入流程,如果返回的锁为null将不能执行下面的流程,要么重试等待锁释放,要么返回错误.

    锁的调用一般流程:

            var qtLock=TryGetLock(lockKey);
            if(qtLock==null) 
            { 
                //提示不能同时执行操作
                return;
            }
            else  
            {
                //进行业务流程
            }
            //最后别忘了
            qtLock.ReleaseLock();
    

    API 内的范例:

     code = StatusCode.OK;
     
     //传入超时时间,可以一直等待到超时过期
     var lockSaveReceipt = this.Context.TryGetLock($"{nameof(SaveReceipt)}.{valueArgs.ReceiptArgs.ReceiptId}");
     if (lockSaveReceipt == null)
     {
         code = PublicErrorCode.SaveReceiptByUsed.ToCode();
         return null;
     }
     
     try{
         //todo 业务操作1
         //todo 业务操作2
         //...
     }
     finally
     {
         lockSaveReceipt.ReleaseLock();
     }
    
    展开全文
  • redis实现分布式事务锁

    千次阅读 2020-05-21 10:55:06
    分布式锁 分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。通俗的讲就是,一间厕所就这一个坑,我先来了,上。只有我走之后,打开了,你才能进去,然后你在上。...
  • 分布式事务锁详解

    千次阅读 2018-10-30 18:51:35
    分布式锁详解 大多数互联网系统都是分布式部署的,分布式部署确实能带来性能和效率上的提升,但为此,我们就需要多解决一个分布式环境下,数据一致性的问题。 当某个资源在多系统之间,具有共享性的时候,为了...
  • Redis分布式事务锁实现

    万次阅读 2017-04-25 22:24:40
    Redis事务锁在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。本文采用Spring Data Redis实现一下Redis的分布式事务锁
  • 关于Redisson分布式事务锁

    千次阅读 2019-05-15 07:48:31
    Redisson配置类 /** * @author hwq * @date 2019/05/02 ... log.info("Redisson分布式锁释放"); } log.info("关闭订单任务结束"); } 复制代码 转载于:https://juejin.im/post/5cdbc3c55188256956222a89
  • 分布式事务锁 首先, zk 下有个 locker 持久节点,持久节点下可以创建多个临时节点 node_n 。当客户端期望获得分布式锁的时候,他会在 locker 下通过 create ()方法创建一个临时节点 node_n 然后,...
  • Redis作Java分布式锁  我们都知道redis现在成为越来越多人作为缓存工具的选择,redis在性能、操作等方面上有着独特的优势。 1. 检查reids版本   因为redis是在2.6版本后才内置了Lua脚本解释器,所以也就是说要用...
  • 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据库机制,对记录进行锁定,...利用排它将并行转化为串行操作,但该方案的性...
  • 分布式事务和分布式

    千次阅读 2021-03-14 23:43:05
    一、分布式事务 1.1 背景 传统事务ACID是基于单数据库的本地事务,仅支持单机事务,并不支持跨库事务。但随着微服务架构的普及,业务的分库分表导致一个大型业务系统往往由若干个子系统构成,这些子系统又拥有各自...
  • 分布式+分布式事务面试题 什么是分布式? 在分布式系统之间,保证某些系统资源同步访问的一种方式。 如: 减库存的接口 多应用访问时都要对库存数据做操作,可能会造成超卖问题 可以通过分布式解决。 ...
  • 分布式事务 因为分布式的出现,事务A和事务B是在不同服务器上不同连接,想要同时回滚 那么就得使用分布式事务 分布式事务和事务的传播行为的区别 事务的传播行为是不涉及分布式问题的,是在一个微服务中的,只是...
  • 分布式锁三种实现方式: 1. 基于数据库实现分布式锁; 2. 基于缓存(Redis等)实现分布式锁; 3. 基于Zookeeper实现分布式锁; 一, 基于数据库实现分布式锁 1. 悲观 利用select … where … for update 排他 ...
  • 我们在单机服务器,出现资源的竞争,一般使用synchronized 就可以解决,但是在分布式的服务器上,synchronized 就无法解决这个问题,这就需要一个分布式事务锁。除此之外面试,基本会问springboot、Redis,然后都会...
  • SpringCloud认识五之分布式分布式事务

    万次阅读 多人点赞 2019-01-10 22:44:35
    那么也带来了线程安全问题,比如一个商城系统,下单过程可能由不同的微服务协作完成,在高并发的情况下如果不加锁就会有问题,而传统的加锁方式只针对单一架构,对于分布式架构是不适合的,这时就需要用到分布式锁。...
  • 问题描述:某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 方案一 利用数据库机制,通过对记录进行锁定,再进行操作 ...利用排它将并行转化为串行操作,但该方案的
  • 分布式分布式事务 分布式 基于MySQL数据库 这种方式一般采用数据库乐观,不推荐使用 基于redis 加锁:setnx命令,key是的唯一标志,可以为想要加锁的资源设置对应的key,value暂时设置为1,即 setnx...
  • 今晚接到项目经理发来的数据库问题,报错为ORA-02049: 超时: 分布式事务处理等待,第一时间感觉是维护的数据库的dblink问题,因为现在维护的这些数据库使用大量dblink,70%以上的查询都使用dblink,查看对于的存储...
  • 一、分布式锁 1、什么是分布式锁? 场景1:常规的我们多线程访问同一代码块的时候,为了保证同一时间只能 由一个线程访问,保证数据安全一致性,通常我们使用synchronized关键字来对方法加锁,以达到保证数据安全...
  • springboot 在单机模式下很好解决抢票,秒杀等需要一个一个执行的业务,可以使用jvm自带的synchronized进行上,...方法1:单纯使用 redis 作为分布式锁,比较简单,但是存在几个很难完美解决的问题。 // 获取原...
  • 分布式事务

    2020-01-09 17:12:24
    深入理解分布式事务 分布式事务及其一致性协议 分布式 redis分布式 下面这个的配置文件有个地方写错了,在RedissonManager类中改成这样 config.useSingleServer().setAddress("redis://127.0.0.1:6379"); 高...
  • 分布式分布式事务的理解

    千次阅读 2020-01-04 23:15:49
    一、什么是分布式, 什么是分布式事务? 1.1、 分布式: 多进程的并发问题(传统的单体系统中我们可以用Synchronized、Lock等方式保证数据的安全,多进程中这个无效) 1.2、分布式事务:多进程的事务管理,...
  • 分布式趋势 目前几乎很多大型网站及应用都是分布式部署的,分布式场景中我们也都会遇到一个非常重要的问题:数据一致性。正如分布式的CAP理论说的一样:“任何一个分布式系统都无法同时满足一致性(Consistency)、...
  • 1、关于分布式锁的了解? 原理:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。 具备的条件: ①分布式环境下,一个方法在同一时间只能被一个机器的一个线程执行 ②高可用的获取和释放...
  • 问题描述 最近有个项目功能需求是需要我们...即需要在mysql和elasticsearch数据库间保证分布式数据的原子性。那该如何做呢? 具体问题业务描述 具体需求是mysql数据库中存在一张表学生游戏积分表,积分表的每条记...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 99,652
精华内容 39,860
关键字:

分布式事务锁

友情链接: 问题积累.zip