扫一扫二维码
进群一起备考
查看更多当前 - 案例分析 - Web应用设计
简单
案例题
2024年5月第4题
简单
案例题
2024年5月第4题
#必须掌握
#超纲
在分布式系统中,由于多个节点同时操作共享资源,容易产生竞争条件和资源冲突问题。为了保证数据一致性和系统的稳定性,需要一种有效的分布式锁机制来协调各节点对共享资源的访问。为了简化分布式锁的实现并提高性能,张工提出了一种利用数据库主键索引的方法来实现分布式锁。该方法的核心思想是利用数据库的唯一性约束和事务特性,通过对特定记录的插入和删除操作来实现锁的获取和释放。
分值(9分)
基于数据库实现分布式锁的缺点。
参考答案
基于数据库实现分布式锁虽然实现简单、依赖少,但存在明显缺点:在高并发场景下性能较差,容易成为系统瓶颈;若服务异常未能释放锁,易导致死锁;可重入性和公平性支持弱;扩展性差,难以支撑大规模分布式系统的稳定运行。因此,在对性能和可靠性要求较高的系统中,通常不推荐使用数据库作为分布式锁的实现方式。
凯恩解析
基于数据库实现分布式锁常见的实现方式主要有以下两种:
1. 利用唯一索引插入
基本原理是 唯一性约束充当“互斥机制”,确保同一时间只有一个客户端能获得锁。
- 创建一张锁表,如
distributed_locks (lock_key VARCHAR PRIMARY KEY, owner_id VARCHAR, expire_time DATETIME) - 某客户端尝试通过插入一条唯一的
lock_key记录来加锁:
INSERT INTO distributed_locks (lock_key, owner_id, expire_time)
VALUES ('my_lock', 'instance_1', NOW() + INTERVAL 10 SECOND);
-
如果插入成功,则加锁成功;如果因主键冲突插入失败,说明锁已被持有。
-
由
owner_id判断是否是当前客户端持有锁,只有持有者才可删除:
DELETE FROM distributed_locks WHERE lock_key = 'my_lock' AND owner_id = 'instance_1';
2. 利用数据库的 SELECT ... FOR UPDATE 加悲观锁
基本原理是通过数据库行锁实现互斥。
- 在锁表中先插入一条标志性记录。
- 使用事务和
SELECT ... FOR UPDATE对该记录加锁。
BEGIN;
SELECT * FROM distributed_locks WHERE lock_key = 'my_lock' FOR UPDATE;
-- 执行临界区代码
COMMIT;
这种方法的主要的问题是
- 竞争激烈时插入失败频繁。在高并发场景中,大量节点同时尝试 INSERT 锁记录会频繁触发主键冲突,导致性能下降,数据库压力剧增。
- 锁重入难实现。默认情况下无法支持可重入(同一线程/服务可多次加锁),需要额外存储 owner_id 和 lock_count 等字段,并设计相应逻辑,增加实现难度。
- 数据库成为瓶颈。分布式锁操作本质是对数据库的高频写入和查询操作,容易将数据库打满,拖慢主业务性能。