乐观锁、悲观锁和分布式锁,你用对了吗?

乐观锁、悲观锁和分布式锁的使用

后台开发最怕什么?数据被改乱。 把数据库想成公共厨房,锅就是数据。 三个人同时炒菜,锅翻了,菜就糊了。 锁就是排队机制,让锅一次只给一个人用。

下面讲讲我们3种最常用的锁:乐观锁、悲观锁、分布式锁。

1. 乐观锁

使用场景

适合冲突少的场景。比如用户修改自己的资料、库存更新不频繁的情况。

实际案例

我们有个商品表,结构大概是这样的:

sql 复制代码
CREATE TABLE product (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  stock INT,
  version INT DEFAULT 0
);

注意那个version字段,这就是乐观锁的关键。

当用户下单时,我们会这样更新库存:

sql 复制代码
UPDATE product 
SET stock = stock - 1, version = version + 1 
WHERE id = 1001 AND version = 2;

只有当当前版本是2的时候,才允许扣减库存,并把版本号加1。

如果两个请求同时来,第一个执行完后版本变成3,第二个请求因为version=2不成立,更新就会失败。这时候程序就知道:"哦,有人抢先改了,我得重新查一下库存再处理。"

小结

  • 优点:性能好,不阻塞
  • 缺点:冲突多了会反复重试
  • 适合:读多写少、并发不高的场景

2. 悲观锁:先上锁,再操作

使用场景

适合冲突频繁的场景。比如秒杀、抢票这种大家一窝蜂涌进来的情况。

实际案例

还是上面那个商品表,但这次我们用悲观锁:

sql 复制代码
BEGIN;

-- 先锁定这条记录,别人不能动
SELECT * FROM product WHERE id = 1001 FOR UPDATE;

-- 查到库存是5,减1
UPDATE product SET stock = 4 WHERE id = 1001;

COMMIT;

FOR UPDATE这个语句很关键,它会把这行数据锁住,直到事务结束。其他人想执行同样的查询,就得排队等着。

这样就能保证同一时间只有一个请求能修改库存,彻底避免超卖。

小结

  • 优点:简单直接,不会超卖
  • 缺点:性能差,容易阻塞
  • 适合:高并发、强一致性的场景

3. 分布式锁:跨机器的协调

使用场景

当你有多个服务实例(比如部署了3台服务器),单机锁不管用了,就得用分布式锁。

实际案例

我们系统做了集群,3台服务器一起处理订单。这时候用数据库锁或synchronized都没用------锁不住别的机器上的进程。

我们用了 Redis 来实现分布式锁:

java 复制代码
// 伪代码
String lockKey = "lock:product_1001";

// 尝试加锁,3秒自动过期
Boolean locked = redis.set(lockKey, "1", "NX", "EX", 3);

if (locked) {
    try {
        // 执行扣库存逻辑
        deductStock(1001);
    } finally {
        // 释放锁
        redis.del(lockKey);
    }
} else {
    // 加锁失败,说明别人正在处理
    System.out.println("商品太火爆,再试一次!");
}

这里用到了 Redis 的 SET key value NX EX 命令:

  • NX:只有key不存在时才设置
  • EX:3秒后自动过期(防止程序崩溃导致锁永远不释放)

小结

  • 优点:能跨服务协调
  • 缺点:依赖Redis,实现要小心死锁
  • 适合:分布式系统、集群环境

什么时候用哪种锁?

我总结了个简单判断方法:

场景 推荐用锁
单机应用,偶尔更新 乐观锁
单机应用,高频修改 悲观锁
多台服务器部署 分布式锁
读多写少 乐观锁
写操作特别频繁 悲观锁 or 分布式锁

最后一点心得

锁不是越多越好,而是够用就好。 先想清楚"锅会不会翻",再决定"怎么排队"。 技术就是解决问题的工具!用顺手了,也就没那么可怕了。

本文首发于微信公众号「刘大华的开发笔记」我是大华,专注分享前后端开发的实战笔记。 关注我,少走弯路,一起进步!

相关推荐
寒士obj41 分钟前
Spring容器Bean的创建流程
java·后端·spring
掉鱼的猫1 小时前
Spring AOP 与 Solon AOP 有什么区别?
java·spring
不是光头 强1 小时前
axure chrome 浏览器插件的使用
java·chrome
KaiwuDB1 小时前
KWDB 分布式架构探究——数据分布与特性
数据库·分布式
笨蛋不要掉眼泪2 小时前
Spring Boot集成腾讯云人脸识别实现智能小区门禁系统
java·数据库·spring boot
桃源学社(接毕设)2 小时前
云计算下数据隐私保护系统的设计与实现(LW+源码+讲解+部署)
java·云计算·毕业设计·swing·隐私保护
用户0332126663672 小时前
Java 将 Excel 转换为 HTML:解锁数据在线展示的无限可能
java·excel
字节跳跃者2 小时前
SpringBoot + MinIO + kkFile 实现文件预览,这样操作更安全!
java·后端·程序员
天天摸鱼的java工程师2 小时前
OpenFeign 首次调用卡 3 秒?八年老开发扒透 5 个坑,实战优化到 100ms
java·后端·面试
whitepure2 小时前
万字详解Java集合
java·后端