数据库(Mysql) 实现分布式锁

本文探讨了如何利用MySQL的InnoDB引擎实现分布式锁,强调了唯一索引的重要性以避免并发问题。文中提到的方案无法确保公平锁,并提出了在服务重启、宕机或数据库故障时的处理策略,包括主主同步以防止单点故障。此外,还提及了Spring的@ScheduledLock注解用于防止分布式环境中定时任务的重复执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库(Mysql) 实现分布式锁

​ 基于MySql的InnoDB引擎,只有通过索引进行检索的时候才会使用行级锁,否则会使用表级锁.这个索引一定要创建成唯一索引,否则会出现多个重载方法之间无法同时被访问的问题

以下方案无法实现公平锁. 求大佬指点思路!!!

库表(t_lock)设计

字段类型是否可为空描述
idint主键,自增
relockint锁定次数 为0时,表示未分配锁
methodString加锁方法
ipString获取锁服务ip
lock_timedate锁定时间(设计超时时间)

每个事务锁在表中为一条数据。

  1. 服务启动,查询t_lock表。准备获取锁。

    select * from t_lock;
    
  2. 若表中无数据(服务初次启动),则进行添加:

    INSERT INTO `t_lock`(`id`, `relock`, `method`, `ip`, `lock_time`) VALUES (1, 1, 'test', '127.0.0.1', NOW());
    

    若添加成功,则认为获取到锁。

  3. 若表中有数据,则relock是否为 0。
    1) 若锁定次数为0, 则可以自由获取锁。获取锁执行sql获取锁。

    UPDATE `t_lock` SET `relock` = 1, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 0;
    
    1. 若锁定次数不为0, 则判断ip和method是否一致。若一致,则可以进行重入。执行sql重入锁。
    UPDATE `t_lock` SET `relock` = 2, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 1;  --假定表中锁定次数为 1
    

    ​ 若不一致,则轮询获取锁。获取锁规则为:1. 锁超时 2. 其他人释放锁。
    ​ 锁超时: 锁定时间和当前时间的比较。若时间偏差过大(业务系统自己配置),则可以强制获取锁。

    ​ 其他人释放锁: relock = 0

    UPDATE `t_lock` SET `relock` = 1, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE  `ip` = '127.0.0.1'  AND method = 'test' AND ( ( relock = 2 AND NOW() > DATE_ADD( '2001-09-11 07:35:25', INTERVAL 5 MINUTE )) OR relock = 0 );  --假定表中锁定次数为 2, 超时时间5分钟
    

    ​ 考虑到各个服务器时间可能和数据库时间不一致。 所以使用数据库时间。传入时间为首次查询得到的数据库时间。

    以上update操作,若成功,则获取到相应锁。

  4. 锁释放。

UPDATE `t_lock` SET `relock` = 0, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 1;  --假定表中锁定次数为 1

若被重入,则需多次释放。

注: 此设计 无法体现公平。

异常情况

服务重启或宕机
  1. 重启或宕机后:两种选择 1) 检查锁表,若ip和method一致,则清空锁标记(relock = 0)。2)检查锁表,ip和method一致,则进行重入。(导致所标记无法释放至0),其他线程获取锁,会进行锁超时判断。

数据库宕机

  1. 数据库应设计为主主同步。防止单点。

Spring提供了@ScheduledLock 防止定时任务在分布式环境重复执行

支持多种数据源(jdbc, redis,zk,mongodb …),详情参照:
https://blog.youkuaiyun.com/qq_36341209/article/details/87375794

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值