锁
锁
有限资源的情况下,控制同一时间(段)只有某些线程(用户 / 服务器)能访问到资源。
Java 实现锁:synchronized 关键字、并发包的类
但存在问题:只对单个 JVM 有效
分布式锁
为什么需要分布式锁?
- 有限资源的情况下,控制同一时间(段)只有某些线程(用户 / 服务器)能访问到资源。
- 单个锁只对单个 JVM 有效
分布式锁实现的关键
抢锁机制
怎么保证同一时间只有 1 个服务器能抢到锁?
核心思想 就是:先来的人先把数据改成自己的标识(服务器 ip),后来的人发现标识已存在,就抢锁失败,继续等待。
等先来的人执行方法结束,把标识清空,其他的人继续抢锁。
MySQL 数据库:select for update 行级锁(最简单),或者用乐观锁。
Redis 实现:内存数据库,读写速度快。支持 setnx、lua 脚本,比较方便我们实现分布式锁。
setnx:set if not exists 如果不存在,则设置;只有设置成功才会返回 true,否则返回 false。
注意事项
1)用完锁要释放(腾地方)
2)锁一定要加过期时间
3)如果方法执行时间过长,锁提前过期了?
会导致问题:
- 连锁效应:释放掉别人的锁
- 这样还是会存在多个方法同时执行的情况
解决方案:续期
比如:
boolean end = false;
new Thread(() -> {
if (!end)}{
续期
})
end = true;
4)释放锁的时候,有可能先判断出是自己的锁,但这时锁过期了,最后还是释放了别人的锁
解决方案:Redis + lua 脚本保证操作原子性
// 原子操作
if(get lock == A) {
// set lock B
del lock
}
5)Redis 如果是集群(而不是只有一个 Redis),如果分布式锁的数据不同步怎么办?
解决方案:https://blog.csdn.net/feiying0canglang/article/details/113258494
项目分区导航:⬅️ 16-缓存 | 17-锁 | ➡️ 18-Java 后端万用项目模板介绍
💬 评论