分布式锁相信大家一定不会陌生, 想要用好或者自己写一个却没那么简单
想要达到上述的条件, 一定要 掌握分布式锁的应用场景, 以及分布式锁的不同实现, 不同实现之间有什么区别
二、分布式锁场景如果想真正了解分布式锁, 需要结合一定场景; 举个例子, 某夕夕上抢购 AirPods Pro 的 100 元优惠券
如果使用下面这段代码当作抢购优惠券的后台程序, 我们一起看一下, 可能存在什么样的问题
很明显的就是这段流程在并发场景下并不安全, 会导致优惠券发放超过预期, 类似电商抢购超卖问题。分布式情况下只能通过分布式锁 来解决多个服务资源共享的问题了。
三、分布式锁分布式锁的定义:
保证同一时间只能有一个客户端对共享资源进行操作。
另外有几点要求也是必须要满足的:
1、不会发生死锁。 即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
2、具有容错性。 只要大部分的Redis节点正常运行,客户端就可以加锁和解锁
3、解铃还须系铃人。 加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了
分布式锁实现大致分为三种, Redis、Zookeeper、数据库, 文章以 Redis 展开分布式锁的讨论。
四、分布式锁演进史先来构思下分布式锁实现思路
要求:
首先我们必须保证同一时间只有一个客户端(部署的优惠券服务)操作数量加减。
其次本次客户端操作完成后, 需要让 其它客户端继续执行。
实现:
1、客户端一存放一个标志位, 如果添加成功, 操作减优惠券数量操作
2、客户端二添加标志位失败, 本次减库存操作失败(或继续尝试获取等)
3、客户端一优惠券操作完成后, 需要将标志位释放, 以便其余客户端对库存进行操作
4.1 第一版 setnx向 Redis 中添加一个 lockKey 锁标志位, 如果添加成功则能够继续向下执行扣减优惠券数量操作, 最后再释放此标志位
由于使用的是 Spring 提供的 Redis 封装的 Start 包, 所有有些命令与 Redis 原生命令不相符
1 setIfAbsent(key, val) -> setnx(key, val)