如何将锁设计成?
摘要:分布式锁 1. 什么是分布式锁? 分布式锁是指在分布式系统中,多个进程或线程之间为了避免冲突而对某个共享资源加锁的机制。分布式锁通常用于保证在分布式系统中,只有一个进程或线程能访问某个共享资源。分布式锁可以分为两种:悲观锁和乐观锁。 悲观锁
分布式锁
1. 什么是分布式锁?
分布式锁是指在分布式系统中,多个进程或线程之间为了避免冲突而对某个共享资源加锁的机制。分布式锁通常用于保证在分布式系统中,只有一个进程或线程能访问某个共享资源。分布式锁可以分为两种:悲观锁和乐观锁。
悲观锁是指 每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候,都会先加锁,然后再进行访问。如果其他进程或线程也尝试访问共享资源,那么它们将被阻塞,直到当前进程或线程释放锁。悲观锁保证了共享资源的互斥访问,但可能会导致其他进程或线程长时间等待。传统的关系型数据库里面就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁。
乐观锁是指 每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在修改的时候会判断一下在这个期间别人有没有去更新这个数据,一般使用版本号机制,然后再进行访问。如果其他进程或线程也尝试访问共享资源,那么它们将检查共享资源的版本号,如果版本号相同,则可以继续访问共享资源;如果版本号不同,则表示其他进程或线程已经修改了共享资源,那么当前进程或线程将重新获取共享资源的版本号,并再次检查版本号。乐观锁不会阻塞其他进程或线程,但可能会导致共享资源被错误修改。 乐观锁适用于多读的应用类型,这样可以提高吞吐量。redis就是使用这种check-and-set机制实现事务的。
分布式锁的5种实现方式:
1、基于数据库的锁
2、基于消息队列的锁
3、基于文件系统的锁
4、基于分布式协调服务zookeeper的锁
5、基于 缓存Redis 的锁
1、基于数据库的实现:使用数据库的事务和锁机制来实现分布式锁。优点是可靠性高,支持事务和锁机制,适用于需要强一致性和高可靠性的场景。缺点是性能较低,对数据库性能有一定影响。
基于 MySQL 数据库实现的分布式锁,可以使用以下方法实现:
1)、使用 SELECT ... FOR UPDATE 语句获取锁。
2)、使用 INSERT ... ON DUPLICATE KEY UPDATE 语句获取锁。
3)、使用 CREATE TEMPORARY TABLE ... 语句创建临时表,并使用 SELECT ... FOR UPDATE 语句获取锁。
2、基于缓存的实现:使用缓存系统(如Redis)的原子操作来实现分布式锁。优点是性能较高,支持原子操作,适用于高并发场景。缺点是可靠性相对较低,需要处理缓存故障和失效的情况。
1)、创建一个 Redis 客户端连接。
2)、当一个进程需要获取锁时,它使用 Redis 的 SETNX 命令设置一个指定的 key,同时设置一个过期时间,确保锁在一段时间后自动释放。
3)、如果 SETNX 命令返回 1,表示进程成功获取到锁。
4)、如果 SETNX 命令返回 0,表示锁已经被其他进程持有,进程需要等待一段时间后重试。
5)、当进程完成任务后,释放锁,使用 Redis 的 DEL 命令删除锁对应的 key。
3、基于共享文件系统的实现:使用共享文件系统(如NFS)来实现分布式锁。优点是可靠性高,支持文件系统的原子操作,适用于需要强一致性和高可靠性的场景。缺点是性能较低,对文件系统的性能有一定影响。
使用以下方法实现:
1)、创建一个文件,并将文件的权限设置为只读。
2)、在文件中写入一个字符串,表示锁的持有者。
3)、其他进程在获取锁之前,需要先检查文件是否存在,如果存在,则表示锁已经被持有,需要等待锁被释放。
4)、当锁持有者释放锁时,需要将文件删除。
4、基于消息队列的实现:使用消息队列来实现分布式锁。通过发送和接收消息来控制锁的获取和释放。优点是简单易用,适用于简单的场景。缺点是性能较低,不适用于高并发和高吞吐量的场景。
使用以下步骤实现:
1)、创建一个消息队列。
2)、为每个请求创建一个消息。
3)、将消息发送到消息队列。
4)、等待消息被消费。
5)、如果消息被消费,则获取锁。
6)、释放锁。
5、基于分布式协调服务的实现:使用分布式协调服务(如ZooKeeper、etcd)来实现分布式锁。通过创建临时顺序节点和监听节点变化来控制锁的获取和释放。优点是可靠性高,支持分布式环境,适用于需要高可靠性和一致性的场景。缺点是性能较低,对分布式协调服务的性能有一定影响。
基于 ZooKeeper 实现的分布式锁的详细步骤:
1)、创建一个 ZooKeeper 客户端连接。
2)、在 ZooKeeper 中创建一个持久性节点作为锁的根节点。
3)、当一个进程需要获取锁时,它在锁的根节点下创建一个临时顺序节点。
