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

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

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<String> 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
    }
}
目录
相关文章
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
427 5
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
293 9
|
存储 分布式计算 Hadoop
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
555 7
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
1288 161
|
存储 NoSQL Java
Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?
【10月更文挑战第29天】Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?
571 1
|
NoSQL Java 数据库
Java分布式锁
Java分布式锁
282 0
|
缓存 Java 数据库
JAVA分布式CAP原则
JAVA分布式CAP原则
385 0
|
缓存 NoSQL Java
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
327 3
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
|
分布式计算 NoSQL Java
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
271 2