背景
最近在业务中出现用户重复提交退款,因为重复提交时间差极端,在加上中间网络延迟,导致请求到达服务端时,出现两个请求的时间差在毫秒级,从而导致重复数据;后来在商户端也出现类似的情况,因此开始在关键业务中使用分布式锁来解决这类问题。
分布式锁是控制分布式系统之前访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
实现分布式锁,主要有以下三个方面为重点:
-
获取锁
在并发情况下,保证只有一个client能够获取到锁。
-
释放锁
client在正常处理业务结束之后主动释放锁;client处理过程中出现异常未能主动释放锁,需要系统能够主动释放锁,保证不会出现死锁。
-
其他client获知锁被释放
当锁被释放之后,其他client可以获知到锁已经被释放,并可以重新竞争锁。
数据库锁
思想:使用订单号(唯一)作为数据库表的主键或索引,每笔订单在访问共享资源时,通过下面的方法来保证互斥。
// 获取锁
int lock() {
return sql.exec("insert into t_dlm(f_oid, f_remark) values('1', 'task1')");
}
// 释放锁
int unlock() {
return sql.exec("delete from t_dlm where f_oid='1'"