学seo可以做网站吗,友链大全,手机端网站开发技术,字体怎么安装wordpress#x1f604; 19年之后由于某些原因断更了三年#xff0c;23年重新扬帆起航#xff0c;推出更多优质博文#xff0c;希望大家多多支持#xff5e; #x1f337; 古之立大事者#xff0c;不惟有超世之才#xff0c;亦必有坚忍不拔之志 #x1f390; 个人CSND主页——Mi… 19年之后由于某些原因断更了三年23年重新扬帆起航推出更多优质博文希望大家多多支持 古之立大事者不惟有超世之才亦必有坚忍不拔之志 个人CSND主页——Micro麦可乐的博客 《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程入门到实战 《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程从基础知识到项目实战 《设计模式》专栏以实际的生活场景为案例进行讲解让大家对设计模式有一个更清晰的理解 如果文章能够给大家带来一定的帮助欢迎关注、评论互动 深度解析分布式锁及实现方案 引言什么是分布式锁分布式锁的应用场景分布式锁的设计原则分布式锁的实现方案基于数据库的实现基于缓存的实现基于ZooKeeper的实现 分布式锁的注意事项结语 引言
在分布式系统中分布式锁是协调多个节点对共享资源进行互斥访问的关键技术。本文将深入研究分布式锁的概念、应用场景并详细介绍三种常见的实现方案包括基于数据库、基于缓存以Redis为例和基于ZooKeeper的实现。
什么是分布式锁
分布式锁是一种在分布式系统中实现协同访问共享资源的机制目的是确保在分布式环境中对共享资源的互斥访问避免数据不一致性、并发冲突等问题。
分布式锁的应用场景 避免重复任务 确保在分布式系统中某个任务只被执行一次防止重复执行。 资源竞争控制 协调多个节点对共享资源的访问保证资源访问的互斥性。 分布式事务 在分布式事务中用于协调多个参与者对资源的访问确保事务的一致性。
分布式锁的设计原则
Redis的官网在新窗口打开上对使用分布式锁提出至少需要满足如下三个要求
互斥属于安全性在任何给定时刻只有一个客户端可以持有锁。无死锁属于有效性即使锁定资源的客户端崩溃或被分区也总是可以获得锁通常通过超时机制实现。容错性属于有效性只要大多数 Redis 节点都启动客户端就可以获取和释放锁。
除此之外分布式锁的设计中还可以/需要考虑 加锁解锁的同源性A加的锁不能被B解锁 获取锁是非阻塞的如果获取不到锁不能无限期等待 高性能加锁解锁是高性能的 分布式锁的实现方案
下面介绍几种我们日常工作中常见的分布式锁的实现方案
1、基于数据库实现分布式锁 基于数据库表锁表很少使用乐观锁(基于版本号)悲观锁(基于排它锁) 2、基于 redis 实现分布式锁 单个Redis实例setnx(key,当前时间过期时间) LuaRedis集群模式Redlock 3、基于 zookeeper实现分布式锁 临时有序节点来实现的分布式锁,Curator 基于数据库的实现
通过数据库的事务特性来实现分布式锁使用数据库行级锁或唯一索引。
详细代码示例使用PostgreSQL
// 加锁
public boolean tryLock(String lockKey, String clientId, int expireTime) {try (Connection connection dataSource.getConnection()) {connection.setAutoCommit(false);try (PreparedStatement preparedStatement connection.prepareStatement(INSERT INTO distributed_lock (lock_key, client_id, expire_time) VALUES (?, ?, ?) ON CONFLICT (lock_key) DO NOTHING)) {preparedStatement.setString(1, lockKey);preparedStatement.setString(2, clientId);preparedStatement.setTimestamp(3, new Timestamp(System.currentTimeMillis() expireTime));int affectedRows preparedStatement.executeUpdate();if (affectedRows 0) {connection.commit();return true;} else {connection.rollback();return false;}}} catch (SQLException e) {// 处理异常return false;}
}// 解锁
public void unlock(String lockKey, String clientId) {try (Connection connection dataSource.getConnection()) {try (PreparedStatement preparedStatement connection.prepareStatement(DELETE FROM distributed_lock WHERE lock_key ? AND client_id ?)) {preparedStatement.setString(1, lockKey);preparedStatement.setString(2, clientId);preparedStatement.executeUpdate();}} catch (SQLException e) {// 处理异常}
}基于缓存的实现
利用分布式缓存系统以Redis为例通过其原子性操作来实现分布式锁。
详细代码示例使用Redis
// 加锁
public boolean tryLock(String lockKey, String clientId, int expireTime) {try (Jedis jedis jedisPool.getResource()) {String result jedis.set(lockKey, clientId, NX, PX, expireTime);return OK.equals(result);}
}// 解锁
public void unlock(String lockKey, String clientId) {try (Jedis jedis jedisPool.getResource()) {jedis.del(lockKey);}
}
基于ZooKeeper的实现
利用ZooKeeper的临时有序节点特性实现分布式锁。
public boolean tryLock(String lockKey, String clientId, int expireTime) {try {String lockPath zooKeeper.create(lockKey /, clientId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);ListString children zooKeeper.getChildren(lockKey, false);Collections.sort(children);if (clientId.equals(children.get(0))) {return true;} else {zooKeeper.delete(lockPath, -1);return false;}} catch (Exception e) {// 处理异常return false;}
}public void unlock(String lockKey, String clientId) {try {ListString children zooKeeper.getChildren(lockKey, false);for (String child : children) {if (child.startsWith(clientId)) {zooKeeper.delete(lockKey / child, -1);}}} catch (Exception e) {// 处理异常}
}分布式锁的注意事项
死锁和宕机 考虑在获取锁的过程中可能发生的节点宕机和死锁情况确保系统的可用性。 锁的释放 确保锁在适当的时候被释放防止出现死锁或者长时间占用锁的情况。 锁粒度 合理选择锁的粒度过大的粒度可能导致性能问题而过小的粒度可能导致锁争用。 结语
分布式锁是分布式系统中常用的同步机制通过对共享资源的互斥访问确保系统的一致性。在选择实现方案时需要根据实际场景和系统要求综合考虑保证分布式锁的性能、可靠性和可维护性。在实际应用中可以根据业务需求选择适当的实现方案。