茅台酒网站建设方案,网站 动态 静态,app开发公司排行榜做软件的公司,天津网站备案技术主题
在分布式系统中#xff0c;面对分布式微服务日益流行的场景#xff0c;分布式锁一直是分布式系统老生常谈的内容。分布式锁可以防止用户重复点击#xff0c;对于电商场景中#xff0c;分布式锁可以防止用户重复下单#xff0c;给用户带来更好的体验。
技术实现…技术主题
在分布式系统中面对分布式微服务日益流行的场景分布式锁一直是分布式系统老生常谈的内容。分布式锁可以防止用户重复点击对于电商场景中分布式锁可以防止用户重复下单给用户带来更好的体验。
技术实现方式
一基于Redis的实现方式
通过在Redis中存储一个唯一的key利用Redis的原子性操作来实现锁的获取和释放
二基于ZooKeeper的实现方式
利用Zookeeper的节点临时性和唯一性特点在一个节点上创建一个临时节点表示锁的占用状态释放锁时直接删除该节点
三基于数据库的实现方式
通过在数据库中创建一张表将表的相关信息作为表的字段通过事务的控制来实现锁的获取和释放
技术具体实现原理
一基于Redis的具体实现原理
Redis操作必须是原子的获取锁和释放锁的Redis操作必须是原子的可以使用Redis的setnx命令实现。它可以原子地执行一次 SET 命令当且仅当 key 不存在可以设置成功。设置过期时间为避免死锁需要设置锁的过期时间若处理业务超时导致锁未被释放则其他节点可以重新竞争获取锁。使用Redis的expire命令可以设置key的过期时间。避免误删为避免误删其他线程的锁建议在删除前先判断锁是否属于自己。尽管不同线程生成的随机字符串保持一定的唯一性但是无法完全避免重复。
二基于ZooKeeper的具体实现原理
ZooKeeper操作必须是原子的获取锁和释放锁的ZooKeeper操作必须是原子的可以使用ZooKeeper的create命令实现。它可以原子地创建一个唯一且临时的节点。设置临时节点在ZooKeeper中创建一个临时节点表示锁的占用状态。当该节点的客户端断开连接或删除该节点时ZooKeeper将自动清除该节点。利用顺序号在创建临时节点时可以利用ZooKeeper中的顺序号进行排序使得节点可以按照一定的顺序排列。其他客户端在同样的目录下依照节点顺序创建临时节点获得锁的客户端是首个创建临时节点的客户端。避免死锁由于删除节点操作可以避免死锁因此在释放锁的时候需要删除该节点。如果释放锁的时候出现异常导致无法删除节点可以设置一个超时时间让ZooKeeper自动删除该节点。处理异常情况在分布式系统中可能会出现各种异常情况比如网络异常、ZooKeeper节点宕机等情况需要对这些异常情况进行处理。通常的做法是捕获异常并释放锁。
三基于数据库的实现原理
基于数据库乐观锁实现分布式锁的方法是为每个需要锁定的资源在数据库中创建一个对应的记录记录包含以下信息
资源名称resource当前锁定者的标识owner最后一次锁定时间last_lock_time版本号version
其中owner、last_lock_time 和 version 可以使用数据库的行版本号实现而资源名称是唯一的。
实现步骤如下
当需要锁定资源时在数据库中执行以下 SQL 语句
UPDATE lock_table SET owner当前线程标识, last_lock_timeNOW(), versionversion1
WHERE resource资源名称 AND owner IS NULL;该语句会尝试更新 lock_table 表中指定资源的记录并将 owner 设置为当前线程的标识。如果更新成功则表示当前线程获取了锁如果更新失败则表示有其他线程正在持有该资源的锁。
当释放锁时在数据库中执行以下 SQL 语句
UPDATE lock_table SET ownerNULL, last_lock_timeNOW(), versionversion1
WHERE resource资源名称 AND owner当前线程标识 AND version当前版本号;该语句会尝试将持有资源锁的线程标识和版本号更新为 NULL 和当前版本号1。如果更新成功则表示当前线程成功释放了锁如果更新失败则表示要么该资源并没有被当前线程锁定要么在锁定期间该资源的版本号已经被修改了。
需要注意的是由于乐观锁是基于数据版本号的因此在高并发情况下会有一定的冲突率需要在应用程序中进行重试或回退等操作来保证锁定操作的可靠性。另外该实现方案也需要确保数据库的事务隔离级别为 SERIALIZABLE以避免并发情况下的数据不一致性问题。
四数据库悲观锁
数据库的被关锁 此外MySQL 还支持通过 SELECT FOR UPDATE 或 SELECT … LOCK IN SHARE MODE 语句来实现悲观锁。例如
SELECT field1, version FROM your_table WHERE id your_id FOR UPDATE;该语句会将该记录上锁防止其他事务修改该记录从而实现悲观锁的效果。在 MySQL 中悲观锁机制使用的是表锁和行锁因此在高并发情况下也需要注意锁冲突导致的性能问题。