实现分布式锁

发布于:2025-07-23 ⋅ 阅读:(17) ⋅ 点赞:(0)

在黑马点评项目中,在实现分布式锁的时候提到了实现的几种方式,本文来简单了解一下。

​一、MySQL、Redis、ZooKeeper 是不是都是“数据库”?​

严格来说,​​三者的定位和功能差异很大​​,但广义上都可以视为“数据存储系统”,不过它们的核心设计目标和适用场景完全不同。我们可以从“数据模型”和“核心用途”两个维度区分:

​类型​ ​MySQL​ ​Redis​ ​ZooKeeper​
​核心定位​ 关系型数据库(OLTP,事务型存储) 内存键值数据库(缓存/分布式工具) 分布式协调系统(服务治理/元数据管理)
​数据模型​ 结构化数据(表、行、列,SQL支持) 半结构化数据(键值对+丰富数据结构) 树形结构(ZNode节点,小文件存储)
​存储方式​ 磁盘为主(内存缓存加速) 内存为主(磁盘持久化可选) 内存+磁盘(强一致性,少量写入)
​典型用途​ 业务数据的持久化存储(如订单、用户) 缓存、会话、计数器、分布式锁等 服务注册发现、配置中心、分布式锁等

​总结​​:MySQL是传统关系型数据库,Redis是高性能内存数据库,ZooKeeper是分布式协调工具(虽能存数据,但核心是解决分布式系统的一致性问题)。

​二、三者都能实现分布式锁吗?MySQL的“排他锁”是什么?​

是的,三者都能实现分布式锁,但实现方式和适用场景差异极大。我们逐个分析:

1. ​​MySQL 实现分布式锁:基于表锁或行锁​

MySQL的锁是数据库原生的​​排他锁(Exclusive Lock,X锁)​​,通过SQL语句显式获取。
​原理​​:利用数据库的行锁或表锁,在更新或查询时锁定资源,其他事务需等待锁释放后才能操作。
​示例(行锁)​​:

-- 开启事务
BEGIN;
-- 尝试获取锁(通过FOR UPDATE锁定某一行)
SELECT * FROM distributed_lock WHERE lock_name = 'order_lock' FOR UPDATE;
-- 如果未获取到锁(无结果),则回滚并重试;若获取到锁,执行业务逻辑
UPDATE distributed_lock SET owner = 'current_server' WHERE lock_name = 'order_lock';
COMMIT;

​特点​​:

  • 依赖数据库的事务和锁机制,强一致性(ACID)。
  • 性能较差(每次加锁需数据库交互,网络延迟高)。
  • 锁超时需手动处理(如设置wait_timeout,否则锁可能永久占用)。
2. ​​Redis 实现分布式锁:基于原子命令或RedLock​

Redis的分布式锁是其经典功能,核心依赖SETNX(Set If Not Exists)命令的原子性。
​原理​​:通过SET key value NX PX timeout命令原子性地设置锁(仅当key不存在时设置,并自动过期)。
​示例(单实例)​​:

// Java中使用Redisson的RLock(底层即基于Redis的SETNX+过期时间)
RLock lock = redisson.getLock("order_lock");
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS); // 等待10秒,锁自动30秒过期
if (isLocked) {
    try {
        // 执行业务逻辑
    } finally {
        lock.unlock();
    }
}

​优化版本(RedLock)​​:为避免单实例Redis故障导致锁失效,Redis作者提出RedLock算法(通过多个独立Redis实例投票获取锁)。
​特点​​:

  • 性能高(内存操作,网络延迟低)。
  • 需处理锁续期(Redisson的“看门狗”自动续期)。
  • 弱一致性(依赖Redis持久化配置,极端情况下可能丢锁)。
3. ​​ZooKeeper 实现分布式锁:基于临时顺序节点​

ZooKeeper的分布式锁基于其​​树形节点结构​​和​​Watcher机制​​,核心是利用“临时顺序节点”的特性。
​原理​​:

  1. 所有客户端在锁路径(如/lock)下创建临时顺序节点(如/lock/node-000001)。
  2. 客户端检查自己创建的节点是否是当前最小的节点:
    • 若是,获取锁;
    • 若否,监听前一个节点的删除事件(Watcher),等待前一个节点释放锁。
  3. 锁释放时(客户端主动删除节点或会话超时自动删除),触发后续节点的Watcher,唤醒下一个客户端获取锁。
    ​特点​​:
  • 强一致性(ZooKeeper保证分布式一致性)。
  • 自动失效(客户端会话断开,临时节点自动删除,避免死锁)。
  • 公平锁(按节点顺序分配锁)。

​三、三者的核心区别总结​

​维度​ ​MySQL​ ​Redis​ ​ZooKeeper​
​核心目标​ 持久化存储结构化业务数据 高性能内存存储+分布式工具 分布式系统协调(一致性、元数据管理)
​数据存储​ 磁盘为主(事务优先) 内存为主(持久化可选) 内存+磁盘(强一致性,少量写入)
​分布式锁特性​ 强一致但性能差,需手动处理超时 高性能但需处理续期,弱一致性 强一致、自动失效、公平锁
​典型场景​ 订单、用户等核心业务数据存储 缓存、会话、计数器、异步队列 服务注册发现、配置中心、分布式锁

​四、ZooKeeper 是什么?​

ZooKeeper 是 Apache 旗下的​​分布式协调服务中间件​​,专为解决分布式系统中的一致性问题设计。它的核心能力是提供​​可靠的分布式协调机制​​,让分布式应用可以高效协作。

​ZooKeeper 的核心特性​​:
  1. ​树形数据模型​​:数据以ZNode节点存储,类似文件系统的目录树(每个节点可存少量元数据)。
  2. ​强一致性​​:通过ZAB协议(ZooKeeper Atomic Broadcast)保证分布式环境下数据的最终一致性。
  3. ​Watcher机制​​:客户端可监听节点变化(如创建、删除、数据修改),实现事件通知。
  4. ​临时节点与顺序节点​​:临时节点随会话断开自动删除;顺序节点自动生成全局唯一序号。
​ZooKeeper 的典型用途​​:
  • ​服务注册与发现​​:微服务中记录服务实例的地址(如Dubbo、Kafka)。
  • ​配置中心​​:集中管理分布式系统的配置(修改后实时推送至所有客户端)。
  • ​分布式锁​​:通过临时顺序节点实现公平锁(如前面的锁机制)。
  • ​集群管理​​:监控集群节点存活状态(通过心跳检测临时节点是否存在)。

​总结​

  • ​MySQL​​是“业务数据的仓库”,核心是持久化存储和事务;
  • ​Redis​​是“高性能工具箱”,核心是内存存储和分布式工具(如锁、队列);
  • ​ZooKeeper​​是“分布式协调员”,核心是解决分布式系统的一致性和协作问题。

三者定位完全不同,但在分布式系统中常配合使用(例如:用MySQL存业务数据,Redis做缓存,ZooKeeper做服务发现)。


网站公告

今日签到

点亮在社区的每一天
去签到