zoukankan      html  css  js  c++  java
  • 二十六、聊聊mysql如何实现分布式锁

    分布式锁的功能

    1. 分布式锁使用者位于不同的机器中,锁获取成功之后,才可以对共享资源进行操作

    2. 锁具有重入的功能:即一个使用者可以多次获取某个锁

    3. 获取锁有超时的功能:即在指定的时间内去尝试获取锁,超过了超时时间,如果还未获取成功,则返回获取失败

    4. 能够自动容错,比如:A机器获取锁lock1之后,在释放锁lock1之前,A机器挂了,导致锁lock1未释放,结果会lock1一直被A机器占有着,遇到这种情况时,分布式锁要能够自动解决,可以这么做:持有锁的时候可以加个持有超时时间,超过了这个时间还未释放的,其他机器将有机会获取锁

    预备技能:乐观锁

      通常我们修改表中一条数据过程如下:

    t1:select获取记录R1
    t2:对R1进行编辑
    t3:update R1

      我们来看一下上面的过程存在的问题:

      如果A、B两个线程同时执行到t1,他们俩看到的R1的数据一样,然后都对R1进行编辑,然后去执行t3,最终2个线程都会更新成功,后面一个线程会把前面一个线程update的结果给覆盖掉,这就是并发修改数据存在的问题。

      我们可以在表中新增一个版本号,每次更新数据时候将版本号作为条件,并且每次更新时候版本号+1,过程优化一下,如下:

    t1:打开事务start transaction
    t2:select获取记录R1,声明变量v=R1.version
    t3:对R1进行编辑
    t4:执行更新操作
        update R1 set version = version + 1 where user_id=#user_id# and version = #v#;
    t5:t4中的update会返回影响的行数,我们将其记录在count中,然后根据count来判断提交还是回滚
        if(count==1){
            //提交事务
            commit;
        }else{
            //回滚事务
            rollback;
        }

      上面重点在于步骤t4,当多个线程同时执行到t1,他们看到的R1是一样的,但是当他们执行到t4的时候,数据库会对update的这行记录加锁,确保并发情况下排队执行,所以只有第一个的update会返回1,其他的update结果会返回0,然后后面会判断count是否为1,进而对事务进行提交或者回滚。可以通过count的值知道修改数据是否成功了。

      上面这种方式就乐观锁。我们可以通过乐观锁的方式确保数据并发修改过程中的正确性。

  • 相关阅读:
    UML/ROSE学习笔记系列二:UML的概念模型
    UML/ROSE学习笔记系列五:用况对过程的描述
    UML/ROSE学习笔记系列四:图
    SQLSERVER2005 的作业调度(非原创)
    ORACLE 和SQLSERVER 两表之间批量更新数据对比
    彻底领悟javascript中的exec与match方法(非原创)
    对象,对象集合的简单Xml序列化与反序列化(非原创)
    JIT是库存管理的发展趋势
    UML/ROSE学习笔记系列一:建模原理、概念
    C# 多线程与异步操作实现的探讨(非原创)
  • 原文地址:https://www.cnblogs.com/biao/p/11820176.html
Copyright © 2011-2022 走看看