史上最全的java分布式锁的5种实现方式 您所在的位置:网站首页 java锁实现方式 史上最全的java分布式锁的5种实现方式

史上最全的java分布式锁的5种实现方式

2023-04-15 05:54| 来源: 网络整理| 查看: 265

image.png

基于Redis实现分布式锁Redis是一个高性能的内存数据库,支持分布式锁的实现。基于Redis实现分布式锁的步骤如下:

(1)获取Redis连接

(2)使用setnx命令设置键值对,如果返回值为1,则表示获取锁成功,否则获取锁失败

(3)如果获取锁失败,则使用get命令获取锁的值,并判断当前时间是否大于锁的超时时间,如果是,则使用getset命令设置新的锁值,并判断返回的值是否与获取的值相等,如果相等,则表示获取锁成功,否则获取锁失败

(4)使用del命令删除锁

示例代码如下:

public class RedisLock { private Jedis jedis; private String lockKey; private int expireTime = 30000; private int timeout = 10000; private boolean locked = false; public RedisLock(Jedis jedis, String lockKey) { this.jedis = jedis; this.lockKey = lockKey; } public boolean lock() throws InterruptedException { long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { long expires = System.currentTimeMillis() + expireTime + 1; String expiresStr = String.valueOf(expires); if (jedis.setnx(lockKey, expiresStr) == 1) { locked = true; return true; } String currentValueStr = jedis.get(lockKey); if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { String oldValueStr = jedis.getSet(lockKey, expiresStr); if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { locked = true; return true; } } Thread.sleep(1000); } return false; } public void unlock() { if (locked) { jedis.del(lockKey); locked = false; } } }

基于ZooKeeper实现分布式锁ZooKeeper是一个分布式协调服务,支持分布式锁的实现。基于ZooKeeper实现分布式锁的步骤如下:

(1)创建一个ZooKeeper客户端连接

(2)使用create命令创建一个临时节点,如果创建成功,则表示获取锁成功,否则获取锁失败

(3)如果获取锁失败,则使用exists命令监听锁节点的删除事件,并等待锁释放

(4)使用delete命令删除锁节点

示例代码如下:

public class ZooKeeperLock implements Watcher { private ZooKeeper zooKeeper; private String lockPath; private String lockNode; private CountDownLatch countDownLatch = new CountDownLatch(1); private boolean locked = false; public ZooKeeperLock(ZooKeeper zooKeeper, String lockPath) { this.zooKeeper = zooKeeper; this.lockPath = lockPath; } public boolean lock() throws InterruptedException, KeeperException { lockNode = zooKeeper.create(lockPath + "/lock-", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); List nodes = zooKeeper.getChildren(lockPath, false); Collections.sort(nodes); if (lockNode.equals(lockPath + "/" + nodes.get(0))) { locked = true; return true; } else { String prevNode = lockPath + "/" + nodes.get(Collections.binarySearch(nodes, lockNode.substring(lockNode.lastIndexOf("/") + 1)) - 1); zooKeeper.exists(prevNode, this); countDownLatch.await(); return locked; } } public void unlock() throws InterruptedException, KeeperException { zooKeeper.delete(lockNode, -1); locked = false; } @Override public void process(WatchedEvent event) { if (event.getType() == Event.EventType.NodeDeleted) { countDownLatch.countDown(); } } }

基于数据库实现分布式锁数据库可以通过加锁机制来实现分布式锁。基于数据库实现分布式锁的步骤如下:

(1)使用select for update命令查询锁,如果查询结果为空,则表示获取锁成功,否则获取锁失败

(2)如果获取锁失败,则使用select命令查询锁,并设置超时时间,等待锁释放

(3)使用update命令更新锁

示例代码如下:

public class DatabaseLock { private Connection connection; private String lockTable; private String lockName; private int expireTime = 30000; private int timeout = 10000; private boolean locked = false; public DatabaseLock(Connection connection, String lockTable, String lockName) { this.connection = connection; this.lockTable = lockTable; this.lockName = lockName; } public boolean lock() throws SQLException, InterruptedException { long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { PreparedStatement selectStatement = connection.prepareStatement("SELECT * FROM " + lockTable + " WHERE name = ? FOR UPDATE"); selectStatement.setString(1, lockName); ResultSet resultSet = selectStatement.executeQuery(); if (!resultSet.next()) { PreparedStatement insertStatement = connection.prepareStatement("INSERT INTO " + lockTable + " (name, expires) VALUES (?, ?)"); insertStatement.setString(1, lockName); insertStatement.setTimestamp(2, new Timestamp(System.currentTimeMillis() + expireTime)); insertStatement.executeUpdate(); locked = true; return true; } Timestamp expires = resultSet.getTimestamp("expires"); if (expires != null && expires.getTime() < System.currentTimeMillis()) { PreparedStatement updateStatement = connection.prepareStatement("UPDATE " + lockTable + " SET expires = ? WHERE name = ? AND expires = ?"); updateStatement.setTimestamp(1, new Timestamp(System.currentTimeMillis() + expireTime)); updateStatement.setString(2, lockName); updateStatement.setTimestamp(3, expires); int affectedRows = updateStatement.executeUpdate(); if (affectedRows > 0) { locked = true; return true; } } Thread.sleep(1000); } return false; } public void unlock() throws SQLException { if (locked) { PreparedStatement deleteStatement = connection.prepareStatement("DELETE FROM " + lockTable + " WHERE name = ?"); deleteStatement.setString(1, lockName); deleteStatement.executeUpdate(); locked = false; } } }

基于文件系统实现分布式锁文件系统可以通过文件锁来实现分布式锁。基于文件系统实现分布式锁的步骤如下:

(1)使用FileChannel的tryLock方法获取文件锁,如果获取锁成功,则表示获取锁成功,否则获取锁失败

(2)如果获取锁失败,则使用FileChannel的lock方法获取文件锁,并等待锁释放

(3)使用FileChannel的release方法释放文件锁

示例代码如下:

public class FileLock { private FileChannel fileChannel; private FileLock lock; private boolean locked = false; public FileLock(File file) throws IOException { fileChannel = new RandomAccessFile(file, "rw").getChannel(); } public boolean lock() throws IOException, InterruptedException { lock = fileChannel.tryLock(); if (lock != null) { locked = true; return true; } else { lock = fileChannel.lock(); lock = fileChannel.tryLock(); locked = true; return true; } } public void unlock() throws IOException { if (locked) { lock.release(); fileChannel.close(); locked = false; } } }

基于Spring实现分布式锁Spring提供了分布式锁的实现,可以使用Spring进行分布式锁的操作。基于Spring实现分布式锁的步骤如下:

(1)使用@Lock注解标注需要加锁的方法

(2)使用@LockKey注解标注锁的键值

(3)使用@EnableLock注解开启分布式锁

示例代码如下:

@EnableLock public class SpringLock { @Lock(key = "lockKey") public void doSomething() { // do something } @Lock(key = "#id") public void doSomething(@LockKey String id) { // do something } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有