基于mysql关系型数据库实现分布式锁以及存在的问题

本文介绍了一种基于MySQL的分布式锁实现方法,包括加锁、解锁、重试等关键步骤,并探讨了其性能特点及适用场景。

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

思路:

1.加锁:INSERT  INTO tb_lock(lock_name) values ('lock')   执行成功代表获取锁成功

2.释放锁:获取锁成功的请求执行业务操作,执行完成之后通过delete删除对应记录

3.重试:递归

@Data
@TableName("tb_lock")
public class Lock {

    private Long id;
    private String lockName;
}
public void deduct() {
    try {
        //加锁
        
        Lock lock = new Lock();
        lock.setLockName("lock");
        this.lockMapper.insert(lock);
        //1.查询库存信息
        String stock = redisTemplate.opsForValue().get("stock").toString();
        //2.判断库存是否充足
        if (stock != null && stock.length() != 0) {
            Integer st = Integer.valueOf(stock);
            if (st > 0) {
                //3.扣减库存
                redisTemplate.opsForValue().set("stock", String.valueOf(--st));
            }
        }
        //解锁
        this.lockMapper.deleteById(lock.getId());
    }catch (Exception e) {
        e.printStackTrace();
        //重试
        try{
            Thread.sleep(50);
            this.deduct();
        }catch (Exception exception){
            exception.printStackTrace();
        }

    }

}

mysql分布式锁的性能比较差

lock_time 需要在数据库中加一个字段,给锁记录添加一个获取锁时间的列,防止死锁

server_id varchar  通过uuid给服务器生成一个uuid

thread_id  那个线程的id

count 重入次数减为0

防死锁:客户端程序获取到锁之后,客户端程序的服务器宕机。给锁记录添加一个获取锁时间的列。

防误删:借助于id的唯一性来防止误删

原子性:通过一个写操作  如果是多个操作可以借助于mysql的乐观锁或者悲观锁

可重入:可重入 ,记录服务信息以及线程信息,重入次数

自动续期:通过定时任务,只要服务活着,就去重置获取锁的时间。使用服务器内的定时器重置获取锁的系统时间。额外的定时器检查获取锁的系统时间和当前系统时间的差值是否超过了阈值。

单机故障:搭建mysql主备模式

集群情况下锁机制失效问题(依然存在问题,mysql中用分布式锁不太容易实现)

分布式锁(mysql、zookeeper 、redis)

1.简易程序: mysql 》redis(lua脚本) 》zk

2.性能:redis 》zk 》mysql

3.可靠性:zk 》redis =mysql

仅仅满足独占排他和对性能和可靠性要求不高的情况下,选择mysql分布式锁

如果追求极致性能选择:redis分布式锁

追求可靠性:zk

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值