分布式锁的实现

目录

    • 分布式锁的实现
      • 什么是分布式锁
      • 使用场景
      • 分布式锁的满足条件
        • 1.互斥性
        • 2.可重入性
        • 3.容错性
      • 分布式锁的实现方案
        • 1.基于数据库:
          • 锁表实现(很少使用)
          • 乐观锁实现
          • 悲观锁实现
        • 2.基于缓存
          • setnx + expire。
          • setnx + value值是过期时间。
          • set的扩展命令(set ex px nx)。
          • set ex px nx + 校验唯一随机值,再删除。
          • Redisson。
          • Redisson + RedLock。
        • 3.基于ZooKeeper:

分布式锁的实现

什么是分布式锁

分布式锁是一种用于协调分布式系统中多个进程或线程之间对共享资源的访问的机制。在分布式系统中,多个进程或线程同时访问共享资源可能会导致数据不一致或并发冲突的问题。分布式锁通过保证在同一时间只有一个进程或线程能够访问共享资源,从而解决了这些问题。

  • 分布式与单机情况下最大的不同在于其不是多线程而是多进程
  • 多线程由于可以共享堆内存,因此可以简单的采取内存作为标记存储位置。而进程之间甚至可能都不在同一台物理机上,因此需要将标记存储在一个所有进程都能看到的地方

使用场景

分布式锁在分布式系统中广泛应用于各种场景,例如分布式任务调度、分布式事务、分布式缓存等。它可以保证多个进程或线程之间对共享资源的访问的一致性和正确性,提高系统的可靠性和性能。

分布式锁的满足条件

无论采用哪种实现方式,分布式锁都需要满足以下几个条件:

1.互斥性

在同一时间只能有一个进程或线程持有锁。

2.可重入性

同一个进程或线程可以多次获取同一把锁。

3.容错性

当持有锁的进程或线程发生故障时,系统能够自动释放锁。

分布式锁的实现方案

分布式锁可以通过各种方式实现,常见的实现方式包括:

1.基于数据库:

使用数据库的事务和锁机制来实现分布式锁

  • 锁表实现(很少使用)

    创建一张锁表,然后通过操作该表中的数据来实现了。当我们想要获得锁的时候,就可以在该表中增加一条记录,想要释放锁的时候就删除这条记录。

    这里为resource 设置为唯一键,防止对同一资源进行多次锁定,保证唯一

CREATE TABLE ojmall_lock (
	`id` BIGINT NOT NULL AUTO_INCREMENT,
	`resource` int NOT NULL COMMENT '锁定的资源',
	`description` varchar(1024) NOT NULL DEFAULT "" COMMENT '描述',
	PRIMARY KEY (id),
	UNIQUE KEY uiq_idx_resource (resource)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库分布式锁表';

当我们想要获得锁时,可以插入一条数据

INSERT INTO ojmall_lock(resource, description) VALUES (1, 'lock');

当需要释放锁的时,可以删除这条数据:

DELETE FROM ojmall_lock WHERE resource=1;
  • 乐观锁实现

    乐观锁,顾名思义,就是很乐观,每次更新操作,都觉得不会存在并发冲突,只有更新失败后,才重试。

    表中加version字段,每次更新修改,都会自增加一,然后去更新内容时,把查出来的那个版本号,带上条件去更新,如果还是上次那个版本号,就更新,如果不是,表示别人并发修改过了,就继续重试。

    一般需要要设置一下重试次数

  • 悲观锁实现

    在分布式系统中,可以通过数据库悲观锁来实现分布式锁。具体实现步骤如下:

    1. 创建一个数据库表,用于存储锁的信息。表结构可以包括锁的名称、持有者、超时时间等字段。
    2. 当需要获取锁时,向数据库表中插入一条记录,表示该锁已被某个节点持有。可以使用INSERT语句,并设置锁的名称、持有者和超时时间等字段。
    3. 在插入记录时,使用数据库的悲观锁机制,例如使用SELECT FOR UPDATE语句,锁定该记录,避免其他事务对该记录进行修改。
    4. 如果插入记录成功,则表示该节点成功获取到了锁,可以执行相应的业务逻辑。
    5. 如果插入记录失败,则表示该锁已被其他节点持有。可以根据需要选择等待一段时间后重新尝试获取锁,或者直接放弃获取锁。
    6. 在业务逻辑执行完毕后,释放锁。可以通过删除数据库表中的对应记录来释放锁。

    需要注意的是,分布式环境下的数据库悲观锁实现存在一些问题,例如数据库单点故障、网络延迟等。为了解决这些问题,可以使用分布式锁中的其他机制,如基于Redis的分布式锁、基于ZooKeeper的分布式锁等。这些机制可以提供更高的可靠性和性能。

2.基于缓存

使用分布式缓存系统(如Redis)的原子操作来实现分布式锁,

例如通过设置一个特定的缓存键值对来表示锁的状态。

  • setnx + expire。
  • setnx + value值是过期时间。
  • set的扩展命令(set ex px nx)。
  • set ex px nx + 校验唯一随机值,再删除。
  • Redisson。
  • Redisson + RedLock。

3.基于ZooKeeper:

使用ZooKeeper这样的分布式协调服务来实现分布式锁,例如通过创建一个临时节点来表示锁的状态。

参考文章:

https://mp.weixin.qq.com/s?__biz=MzA5NzE1NzY3OA==&mid=2653462355&idx=1&sn=f597248ea9e1f39ace50d26593e3f1a6&chksm=8b792812bc0ea104ad6ad14f6973f9ce4c6fa47c518e28a1638bcd98633a76a25742f3b13395#rd

你可能感兴趣的:(springcloud从零搭建,分布式)