一、什么是分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种机制。在单节点应用中,我们需要对一个共享资源进行多线程访问时,使用普通的锁就能够保证同步循序访问资源,不存在线程安全问题。当你掌握了流量密码后,业务突飞猛进,应用部署需要扩容,进行集群部署。此时,普通的锁已经控制不了集群各节点线程对共享资源的访问,为解决此问题,分布式锁诞生。

二、分布式锁特性与应用场景

三、分布式锁你用对了吗?

使用了分布式锁,为什么你的订单还是有重复支付的记录产生?

先来说故事,小Q已做开发好几年,近期负责一个新项目的订单支付接口开发。在小Q看来,支付API已有,毕竟也有几年工作经验,轻车熟路,知道订单支付要加分布式锁,信心满满,挥一挥手干完一个订单支付接口。系统测试阶段,支付功能正常,没啥BUG。系统上线后,订单支付功能运行良好。突然有一天,客服接到客户反馈"你们这是什么破系统,竟敢重复扣我的血汗钱"。小Q接到项目经理通知后,惊呆了,心想"难道是架构师提供的分布式锁组件有bug?"。

然而并不像小Q想的那样,原因竟是小Q自己的分布式锁使用不当造成的。原来架构师为了防止死锁,提供了一个可以设置锁超时自动释放的加锁方法。而小Q在加锁时也考虑到了死锁的情况,给加锁方法设置了一个10秒的超时释放时间。正常情况下,一个同步支付的请求处理时间不超过2秒,小Q考虑10秒总该够了吧,于是自信地设置了10秒。

小Q在业务处理异常考虑得较少,在支付处理中,支付后需要调用外部服务推送数据,推送数据接口由于异常15秒后报了ReadTimeout。而小Q加锁的代码中正包含调用外部服务推送数据方法。业务要求如果推送数据失败不能影响正常支付,所以小Q用了try..catch,记录失败日志以便后续系统定时任务重新推送。所以推送数据超时后也正常写入了支付数据。

由于用户支付操作等了很久,在12秒的时候又重新发起了一次支付,此时,由于第一次支付的锁释放时间(10秒)已到,锁自动释放。第二次支付请求,在12秒又获得锁,第二次支付也正常完成流程处理。产生了2笔都是支付完成的支付记录。

分布式锁5种(分布式锁你用对了吗)(1)

支付时序图

图中主要有几个问题:

,