当前位置: 首页 > news >正文

分布式锁实现(数据库+Redis+Zookeeper)

1. 数据库分布式锁

实现原理

  1. 基于唯一索引

    • 创建一张锁表,通过唯一索引(如锁名称)保证互斥性。

    • 加锁:插入一条记录,成功则获取锁,失败则重试。

    • 解锁:删除对应记录。

  2. 乐观锁(版本号)

    • 使用版本号字段,更新时检查版本号是否匹配。

  3. 悲观锁(SELECT FOR UPDATE)

    • 通过数据库行锁锁定记录(如 SELECT ... FOR UPDATE)。

          // 基于唯一索引的简单实现(JDBC示例)
public class DatabaseLock {
    private Connection connection;

    public boolean tryLock(String lockKey, String clientId, int expireSeconds) {
        try {
            String sql = "INSERT INTO distributed_lock (lock_key, client_id, expire_time) VALUES (?, ?, ?)";
            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.setString(1, lockKey);
            stmt.setString(2, clientId);
            stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis() + expireSeconds * 1000));
            return stmt.executeUpdate() > 0;
        } catch (SQLException e) {
            return false;
        }
    }

    public void unlock(String lockKey, String clientId) {
        try {
            String sql = "DELETE FROM distributed_lock WHERE lock_key = ? AND client_id = ?";
            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.setString(1, lockKey);
            stmt.setString(2, clientId);
            stmt.executeUpdate();
        } catch (SQLException ignored) {}
    }
}

优缺点

  • 优点

    • 实现简单,无需额外依赖。

  • 缺点

    • 性能低(依赖数据库IO)。

    • 无自动超时机制(需手动清理过期锁)。

    • 单点故障风险。

适用场景

  • 低频并发场景,或作为临时方案。


2. Redis分布式锁

实现原理

  1. 单节点锁(SETNX + EXPIRE)

    • 加锁:使用 SET key value NX EX seconds 原子命令设置锁并指定超时时间。

    • 解锁:通过 Lua 脚本校验客户端唯一标识后删除锁。

  2. RedLock算法(多节点容错):

    • 向多个独立 Redis 节点请求锁,半数以上成功视为加锁成功。

Java代码示例(Jedis客户端)

public class RedisLock {
    private Jedis jedis;
    private String lockKey;
    private String clientId;
    private int expireTime;

    public RedisLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.clientId = UUID.randomUUID().toString();
        this.expireTime = expireTime;
    }

    public boolean tryLock() {
        // 加锁:SET lockKey clientId NX EX expireTime
        String result = jedis.set(lockKey, clientId, SetParams.setParams().nx().ex(expireTime));
        return "OK".equals(result);
    }

    public void unlock() {
        // 解锁:通过Lua脚本保证原子性
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        jedis.eval(luaScript, Collections.singletonList(lockKey), Collections.singletonList(clientId));
    }
}

优缺点

  • 优点

    • 高性能(基于内存操作)。

    • 支持自动超时,避免死锁。

  • 缺点

    • 时钟漂移可能导致锁提前释放。

    • RedLock 算法实现复杂,依赖多节点。

适用场景

  • 高并发场景(如秒杀、限流)。


3. ZooKeeper分布式锁

实现原理

  1. 临时顺序节点

    • 加锁:客户端在 ZooKeeper 的锁目录下创建临时顺序节点。

    • 监听机制:判断当前节点是否为最小节点,是则获取锁;否则监听前一个节点的删除事件。

  2. 临时节点

    • 创建临时节点,成功则获取锁,否则监听节点删除。

public class ZkLock {
    private CuratorFramework client;
    private String lockPath;
    private InterProcessMutex lock;

    public ZkLock(CuratorFramework client, String lockPath) {
        this.client = client;
        this.lockPath = lockPath;
        this.lock = new InterProcessMutex(client, lockPath);
    }

    public boolean tryLock(long timeout, TimeUnit unit) {
        try {
            return lock.acquire(timeout, unit);
        } catch (Exception e) {
            return false;
        }
    }

    public void unlock() {
        try {
            lock.release();
        } catch (Exception ignored) {}
    }
}

// 使用示例
CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", new RetryNTimes(3, 1000));
client.start();
ZkLock zkLock = new ZkLock(client, "/locks/resource");
try {
    if (zkLock.tryLock(10, TimeUnit.SECONDS)) {
        // 执行业务逻辑
    }
} finally {
    zkLock.unlock();
}

优缺点

  • 优点

    • 强一致性(ZooKeeper 的 ZAB 协议)。

    • 自动释放锁(临时节点断开即删除)。

    • 支持公平锁(顺序节点)。

  • 缺点

    • 性能低于 Redis(频繁的节点操作和监听)。

    • 需维护 ZooKeeper 集群。

适用场景

  • 需要强一致性和高可靠性的场景(如金融交易)。


对比总结

特性数据库锁Redis锁ZooKeeper锁
实现复杂度简单中等复杂
性能
可靠性中(依赖集群)
自动超时手动实现支持支持(临时节点)
公平性不支持不支持支持
适用场景低频简单场景高并发场景强一致性场景

选择建议

  1. Redis分布式锁:优先用于高并发场景(如秒杀),需注意锁续期问题。

  2. ZooKeeper分布式锁:用于需要强一致性和公平性的场景(如分布式事务)。

  3. 数据库锁:仅作为简单场景的临时方案。


注意事项

  • 锁超时时间:根据业务操作合理设置,避免锁过早释放。

  • 唯一客户端标识:防止其他客户端误删锁。

  • 容错机制:Redis 建议使用 RedLock,ZooKeeper 需集群部署。

相关文章:

  • redis中的Lua脚本,redis的事务机制
  • 深度学习技术文章质量提升指南(基于CSDN评分算法优化)
  • http代理IP怎么实现?如何解决代理IP访问不了问题?
  • 【nextJs】官网demo学习
  • REACT--组件通信
  • 长短期记忆网络:从理论到创新应用的深度剖析
  • 链表-基础训练(二)链表 day14
  • HAProxy介绍与编译安装
  • 宝塔扩容——阿里云如何操作
  • ‌最新版DeepSeek保姆级安装教程:本地部署+避坑指南
  • 动态规划01背包问题系列一>01背包
  • Spring Boot 如何保证接口安全
  • 请说明C#中的List是如何扩容的?
  • 10.Docker 仓库管理
  • 《Keras 2 :使用 RetinaNet 进行对象检测》:此文为AI自动翻译
  • 运维基线方案说明
  • AI学习指南HuggingFace篇-Hugging Face 的核心工具
  • windows11那些事
  • 计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型民宿推荐系统 hive民宿可视化 民宿爬虫 大数据毕业设计(源码+LW文档+PPT+讲解)
  • k2路由器登录校园网
  • 碧桂园:砸锅卖铁保交房、持续推进保主体,尽快让公司恢复正常经营
  • 巴基斯坦空袭印度多地空军基地,巴战机进入印领空
  • 东方红资管官宣:41岁原国信资管董事长成飞出任新总经理
  • 国家主席习近平在莫斯科出席红场阅兵式
  • 中国以优化营商环境为支点,为全球企业提供可预期市场环境
  • 从上海首个到成片复制,闵行零工市场如何优化劳动就业服务?