分布式锁的几种实现思路
使用场景:
最近遇到一个account dubbo服务的并发注册问题,日志中抛出了大量的主键冲突问题。注册用户过程中有多个SQL操作,且这些SQL可以实现单机本地事务。为解决这么多的日志异常,那么如何处理分布式并发的请求呢?
解决方式:
一: cache方式
原子操作CAS来写缓存,多个并发请求同时只有一个能够写成功。
a) 非幂等的情况没有写成功,则直接返回false。 没有拿到锁。
b) 幂等的情况,需要轮询,三种结果:抢到锁,没有锁轮询成功,没有锁轮询失败,根据业务处理。account因为可以保证事务,所以轮询失败则直接做注册。
那么还有哪些方式可以实现这种分布式请求抢占功能呢?
二: 借助数据库的方式
a) unique key
实现原理:
多个请求同时插入一条记录,只有一条可以插入成功,拿到锁的请求处理完则删掉数据, 没有拿到锁的则返回或者选择轮询尝试。
缺点:
1. 非阻塞锁,立刻返回, 只能轮询或者返回失败
2. 应用宕机了,谁来释放锁
3. 如何实现重入锁
总结:
我觉得我的场景1和3都不是问题,只要考虑应用宕机如何释放锁就好了,如果采用定时任务的话,定时任务需要判断当前时间和这个锁的锁定时间如果大于事务的执行时间则删掉这把锁。但是删掉锁的话当前请求可能只做了一半,其他请求也进来了,就演变成一致性的问题,这就需要分布式事务了。
b) for update
实现原理:
start tran; select * for update 如果成功则立刻返回,如果失败则会等待,解决了非阻塞锁的问题,宕机也会释放锁,重入锁则不行
三:Redis方式
四: zookeeper