美文网首页我爱编程
[180414]mysql实现分布式锁

[180414]mysql实现分布式锁

作者: SpiritWang | 来源:发表于2018-04-14 20:45 被阅读0次

    一、常现的分布式锁

    分布式锁在如今最常见的有3种实现方式:

    1、数据库

    2、缓存

    3、Zookeeper

    二、常现的分布式锁对比

    1、实现难易程度(简 -> 难):数据库 -> 缓存 -> Zookeeper

    2、性能(低 -> 高):数据库 -> Zookeeper -> 缓存

    本次只分析数据库的具体实现,其余2种见后续文章。

    三、数据库版实现思路

           锁,字面意思就是封闭一个物体,一把锁只能用一把钥匙打开。同理,一个分布式的锁,在同一时间也只能由一个用户。

            废话少说,先上表结构:

    --锁表 单库单表

    CREATE TABLE IF NOT EXISTS t_db_lock(   

        Findex INT NOT NULL AUTO_INCREMENT COMMENT '主键',   

        Flock_name VARCHAR(128) NOT NULL COMMENT '锁名key值',    

        Fdeadline DATETIME NOT NULL COMMENT '锁的过期时间',       

        Fstatus FINYINT NOT NULL DEFAULT 1 COMMENT '锁的状态,0-已释放,1-未释放',   

        --主键约束

        PRIMARY KEY (Findex),    

        --唯一约束   

        UNIQUE KEY uniq_Flock_name(Flock_name)

    )ENGINE=INNODB DEFAULT CHARSET=UTF8 COMMENT '锁表-单库单表';

    在程序用可以使用如下结构获取锁

    public boolean getLock(String lockName, Integer expiretime) {

        //开启事务,本程序结合spring事务

        锁对象 = select for update; //锁定当前锁(如果不存在,在mysql默认级别为意向锁)

        if (锁对象 == null) {

            insert 锁; //根据插入返回是否获取锁

        } else {

            //根据锁的状态和过期时间update锁,成功返回true

        }

        return false;

    }

           这个程序有一个致命的错误,在数据库中不存在当前锁名的时候,多线程竞争锁会因为意向锁的问题,导致死锁。

            解决方案:

            (1)降低数据库隔离级别为 Read Commited,这样的话多个事务不会因为意向锁的原因导致死锁了。

            (2)for update的时候可以根据ConcurrentHashMap分段锁的思想设计,提前加入一些锁,根据具体的locaName去hash后取不同的锁。

            (3)也可以捕获异常,然后告诉他获取锁失败。

    数据库的实现大概思路就是这样了,缓存和ZK以后实现后会补相应的文章。

    相关文章

      网友评论

        本文标题:[180414]mysql实现分布式锁

        本文链接:https://www.haomeiwen.com/subject/bkglkftx.html