很多时候,我们爱着,只是自己一个人的事情。那些爱情,拼命却没有回应。也许我们爱上的只是爱情本身。所有的哀伤,最终都不过是自怜的影子
目前我知道的有
-
mysql for update 获取写锁
-
redis
-
通过 setnx/redlock + watch dog
-
setnx redis 单机使用
-
redlock 在redis集群中使用
-
redlock 获取绝大多数锁 超过1/2
-
-
watch dog 用于锁延期
-
-
zookeeper 通过 临时有序节点
- 如果节点获取锁的过程中失效了就断开了
还有说用 etcd Paxos 或 Raft 算法可以实现
MySQL
MySQL中的FOR UPDATE
:
在MySQL中,您可以使用SELECT ... FOR UPDATE
语句来获取行级别的写锁。这种锁机制通常适用于悲观锁场景。具体原理如下:
- 当执行
SELECT ... FOR UPDATE
语句时,MySQL会锁定查询结果中涉及的所有行。在锁定期间,其他事务无法修改这些行,也无法获取相同的写锁。 - 锁定的行在当前事务提交或回滚后会自动释放。
- 这种锁机制依赖于MySQL的事务和隔离级别,适用于单个数据库实例,但在分布式系统中可能无法满足需求。
Redis
Redis中的分布式锁:
a. SETNX
(单机Redis):
SETNX
是Redis中的原子操作,表示“SET if Not eXists”,即仅当键不存在时设置值。- 客户端可以使用
SETNX
命令创建一个键,作为锁。如果成功创建,则认为获取到了锁。否则,锁被其他客户端持有。 - 为防止死锁,需要为锁设置一个超时时间(例如使用
EXPIRE
命令),以便在客户端崩溃或未正确释放锁的情况下自动释放。 - 这种锁机制适用于单个Redis实例,但在Redis集群中可能无法满足需求。
b. Redlock(Redis集群):
- Redlock算法在多个Redis实例上实现分布式锁,确保在任何时候只有一个客户端可以拥有该锁。
- 客户端会尝试在所有Redis实例上创建锁,如果成功获取到大多数实例上的锁(超过一半),则认为已经获得了分布式锁。
- 同样,需要为锁设置一个超时时间,以便在客户端崩溃或未正确释放锁的情况下自动释放。
- 更详细的原理和实现步骤可以参考前面的回答。
c. Watchdog(锁延期):
- Watchdog并不是Redis的分布式锁算法,而是一种辅助机制,用于确保锁在业务处理过程中不会被意外释放。
- 在后台周期性地为锁续租,即延长锁的超时时间。
- Watchdog通常在单独的线程中运行,与业务处理逻辑并发执行。
ZooKeeper
ZooKeeper中的分布式锁:
- ZooKeeper是一个高可用的、分布式的协调服务,可以用来实现分布式锁。在ZooKeeper中,锁通过创建临时有序节点来实现。具体原理如下:
- 客户端请求锁时,在指定的锁目录下创建一个临时有序节点(例如:
/locks/lock_
)。ZooKeeper会自动为这个节点分配一个递增的序号(如:/locks/lock_00000001
)。 - 客户端获取锁目录下所有子节点的列表,并检查自己创建的节点是否是序号最小的节点。如果是,则认为已经获取到了锁。
- 如果客户端创建的节点不是序号最小的节点,它会监视序号仅次于自己的节点(称为“前驱节点”)。如果前驱节点被删除,客户端会重新检查自己的节点是否成为了序号最小的节点。
- 当客户端完成业务逻辑处理后,删除自己创建的临时节点以释放锁。其他等待锁的客户端会收到节点删除的通知,从而有机会尝试获取锁。
- 由于临时节点与客户端会话相关联,如果客户端会话失效(例如由于网络中断),ZooKeeper会自动删除该客户端创建的临时节点。这可以避免死锁和资源无法释放的问题。
- 客户端请求锁时,在指定的锁目录下创建一个临时有序节点(例如: