searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Java分布式锁解决方案

2024-10-10 02:06:21
2
0

以下将详细说明几种常见的Java分布式锁解决方案,并提供具体的实现示例。

1. 基于Redis的分布式锁

实现原理

  1. 使用Redis的SET命令的NX(仅当key不存在时设置)和EX(设置过期时间)选项来实现锁的获取。
  2. 使用DEL命令来释放锁。

示例代码

import redis.clients.jedis.Jedis;
 ​
 public class RedisDistributedLock {
     private Jedis jedis;
     private String lockKey;
     private int expireTime; // 锁的过期时间,单位:秒
 ​
     public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
         this.jedis = jedis;
         this.lockKey = lockKey;
         this.expireTime = expireTime;
     }
 ​
     public boolean tryLock() {
         String result = jedis.set(lockKey, "locked", "NX", "EX", expireTime);
         return "OK".equals(result);
     }
 ​
     public void unlock() {
         jedis.del(lockKey);
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) {
         Jedis jedis = new Jedis("localhost", 6379);
         RedisDistributedLock lock = new RedisDistributedLock(jedis, "my_lock", 10);
 ​
         if (lock.tryLock()) {
             try {
                 // 执行临界区代码
                 System.out.println("执行临界区代码");
             } finally {
                 lock.unlock();
             }
         } else {
             System.out.println("无法获取锁");
         }
     }
 }

2. 基于Zookeeper的分布式锁

实现原理

  1. 在Zookeeper中创建一个顺序节点。
  2. 获取当前节点的前驱节点,如果前驱节点是父节点,则当前节点获得锁。

示例代码

import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZooDefs.Ids;
 ​
 import java.util.List;
 ​
 public class ZookeeperDistributedLock implements Watcher {
     private ZooKeeper zookeeper;
     private String lockPath;
     private String nodePath;
     private String myNodeName;
 ​
     public ZookeeperDistributedLock(ZooKeeper zookeeper, String lockPath) {
         this.zookeeper = zookeeper;
         this.lockPath = lockPath;
     }
 ​
     public boolean tryLock() throws Exception {
         myNodeName = zookeeper.create(lockPath + "/lock-", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
         List<String> children = zookeeper.getChildren(lockPath, this);
         if (children.isEmpty()) {
             return true;
         }
         String firstChild = children.get(0);
         if (myNodeName.endsWith(firstChild)) {
             return true;
         }
         return false;
     }
 ​
     public void unlock() throws Exception {
         zookeeper.delete(nodePath, -1);
     }
 ​
     @Override
     public void process(WatchedEvent event) {
         // 监听事件处理
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) throws Exception {
         ZooKeeper zookeeper = new ZooKeeper("localhost:2181", 5000, new ZookeeperDistributedLock(zookeeper, "/locks"));
         ZookeeperDistributedLock lock = new ZookeeperDistributedLock(zookeeper, "/locks");
 ​
         if (lock.tryLock()) {
             try {
                 // 执行临界区代码
                 System.out.println("执行临界区代码");
             } finally {
                 lock.unlock();
             }
         } else {
             System.out.println("无法获取锁");
         }
     }
 }

3. 使用数据库实现分布式锁

实现原理

  1. 在数据库中创建一个锁表,使用SELECT ... FOR UPDATE来获取锁。
  2. 使用UPDATE来释放锁。

示例代码

import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 ​
 public class DatabaseDistributedLock {
     private Connection connection;
     private String tableName = "distributed_lock";
 ​
     public DatabaseDistributedLock(String url, String username, String password) throws Exception {
         connection = DriverManager.getConnection(url, username, password);
     }
 ​
     public boolean tryLock(String lockName) throws Exception {
         String sql = "SELECT * FROM " + tableName + " WHERE lock_name = ? FOR UPDATE";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setString(1, lockName);
         ResultSet rs = statement.executeQuery();
 ​
         if (!rs.next()) {
             String insertSql = "INSERT INTO " + tableName + "(lock_name) VALUES (?)";
             PreparedStatement insertStatement = connection.prepareStatement(insertSql);
             insertStatement.setString(1, lockName);
             int rows = insertStatement.executeUpdate();
             return rows > 0;
         }
 ​
         return false;
     }
 ​
     public void unlock(String lockName) throws Exception {
         String sql = "DELETE FROM " + tableName + " WHERE lock_name = ?";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setString(1, lockName);
         statement.executeUpdate();
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) {
         try {
             DatabaseDistributedLock lock = new DatabaseDistributedLock("jdbc:mysql://localhost:3306/mydb", "root", "password");
 ​
             if (lock.tryLock("my_lock")) {
                 try {
                     // 执行临界区代码
                     System.out.println("执行临界区代码");
                 } finally {
                     lock.unlock("my_lock");
                 }
             } else {
                 System.out.println("无法获取锁");
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }

总结

以上三种方式是常见的Java分布式锁实现方法。选择哪种方法取决于你的具体需求和技术栈:

  • Redis:简单易用,适合轻量级应用。
  • Zookeeper:功能强大,适合复杂分布式环境。
  • 数据库:适用于事务处理,但性能较低。
0条评论
0 / 1000
邱****先
5文章数
0粉丝数
邱****先
5 文章 | 0 粉丝
原创

Java分布式锁解决方案

2024-10-10 02:06:21
2
0

以下将详细说明几种常见的Java分布式锁解决方案,并提供具体的实现示例。

1. 基于Redis的分布式锁

实现原理

  1. 使用Redis的SET命令的NX(仅当key不存在时设置)和EX(设置过期时间)选项来实现锁的获取。
  2. 使用DEL命令来释放锁。

示例代码

import redis.clients.jedis.Jedis;
 ​
 public class RedisDistributedLock {
     private Jedis jedis;
     private String lockKey;
     private int expireTime; // 锁的过期时间,单位:秒
 ​
     public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
         this.jedis = jedis;
         this.lockKey = lockKey;
         this.expireTime = expireTime;
     }
 ​
     public boolean tryLock() {
         String result = jedis.set(lockKey, "locked", "NX", "EX", expireTime);
         return "OK".equals(result);
     }
 ​
     public void unlock() {
         jedis.del(lockKey);
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) {
         Jedis jedis = new Jedis("localhost", 6379);
         RedisDistributedLock lock = new RedisDistributedLock(jedis, "my_lock", 10);
 ​
         if (lock.tryLock()) {
             try {
                 // 执行临界区代码
                 System.out.println("执行临界区代码");
             } finally {
                 lock.unlock();
             }
         } else {
             System.out.println("无法获取锁");
         }
     }
 }

2. 基于Zookeeper的分布式锁

实现原理

  1. 在Zookeeper中创建一个顺序节点。
  2. 获取当前节点的前驱节点,如果前驱节点是父节点,则当前节点获得锁。

示例代码

import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZooDefs.Ids;
 ​
 import java.util.List;
 ​
 public class ZookeeperDistributedLock implements Watcher {
     private ZooKeeper zookeeper;
     private String lockPath;
     private String nodePath;
     private String myNodeName;
 ​
     public ZookeeperDistributedLock(ZooKeeper zookeeper, String lockPath) {
         this.zookeeper = zookeeper;
         this.lockPath = lockPath;
     }
 ​
     public boolean tryLock() throws Exception {
         myNodeName = zookeeper.create(lockPath + "/lock-", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
         List<String> children = zookeeper.getChildren(lockPath, this);
         if (children.isEmpty()) {
             return true;
         }
         String firstChild = children.get(0);
         if (myNodeName.endsWith(firstChild)) {
             return true;
         }
         return false;
     }
 ​
     public void unlock() throws Exception {
         zookeeper.delete(nodePath, -1);
     }
 ​
     @Override
     public void process(WatchedEvent event) {
         // 监听事件处理
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) throws Exception {
         ZooKeeper zookeeper = new ZooKeeper("localhost:2181", 5000, new ZookeeperDistributedLock(zookeeper, "/locks"));
         ZookeeperDistributedLock lock = new ZookeeperDistributedLock(zookeeper, "/locks");
 ​
         if (lock.tryLock()) {
             try {
                 // 执行临界区代码
                 System.out.println("执行临界区代码");
             } finally {
                 lock.unlock();
             }
         } else {
             System.out.println("无法获取锁");
         }
     }
 }

3. 使用数据库实现分布式锁

实现原理

  1. 在数据库中创建一个锁表,使用SELECT ... FOR UPDATE来获取锁。
  2. 使用UPDATE来释放锁。

示例代码

import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 ​
 public class DatabaseDistributedLock {
     private Connection connection;
     private String tableName = "distributed_lock";
 ​
     public DatabaseDistributedLock(String url, String username, String password) throws Exception {
         connection = DriverManager.getConnection(url, username, password);
     }
 ​
     public boolean tryLock(String lockName) throws Exception {
         String sql = "SELECT * FROM " + tableName + " WHERE lock_name = ? FOR UPDATE";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setString(1, lockName);
         ResultSet rs = statement.executeQuery();
 ​
         if (!rs.next()) {
             String insertSql = "INSERT INTO " + tableName + "(lock_name) VALUES (?)";
             PreparedStatement insertStatement = connection.prepareStatement(insertSql);
             insertStatement.setString(1, lockName);
             int rows = insertStatement.executeUpdate();
             return rows > 0;
         }
 ​
         return false;
     }
 ​
     public void unlock(String lockName) throws Exception {
         String sql = "DELETE FROM " + tableName + " WHERE lock_name = ?";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setString(1, lockName);
         statement.executeUpdate();
     }
 }
 ​
 // 使用示例
 public class Example {
     public static void main(String[] args) {
         try {
             DatabaseDistributedLock lock = new DatabaseDistributedLock("jdbc:mysql://localhost:3306/mydb", "root", "password");
 ​
             if (lock.tryLock("my_lock")) {
                 try {
                     // 执行临界区代码
                     System.out.println("执行临界区代码");
                 } finally {
                     lock.unlock("my_lock");
                 }
             } else {
                 System.out.println("无法获取锁");
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }

总结

以上三种方式是常见的Java分布式锁实现方法。选择哪种方法取决于你的具体需求和技术栈:

  • Redis:简单易用,适合轻量级应用。
  • Zookeeper:功能强大,适合复杂分布式环境。
  • 数据库:适用于事务处理,但性能较低。
文章来自个人专栏
技术开发
5 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0