最近开发用到的分布式锁
程序员文章站
2022-06-02 08:18:23
...
最近开发的场景有分布式任务,任务是创建某些资源,只有创建成功了,某些资源才可使用。此时要考虑用分布式锁,有以下几种思路
1.通过数据库,其实是创建一张表,字段类似于,id,key,values,status(和values字段二选一),createTime。要锁定某个对象时,以其唯一性的字段(例如id)作为key,数据作为values存入,此时为锁定状态;解锁时,将values致为null。写个定时任务,查询createTime,使超时的锁失效。但是这个情况,需要数据库具有强一致性,不能多人同时对一个数据做操作,而且数据库和代码程序是两套程序,不好维护
2.通过程序(代码)
1> 创建一个map,让map充当表的作用,在这个项目存活期间,一直有效,当操作某个对象时,将这个对象,以kv形式放入map,而且要保证map是唯一一个,此时就用到了单例模式;而且map的set和put是只能同时一人操作的,故要加锁。代码如下:
var InstanceMap map[string]interface{}
func GetInstanceMap()map[string]interface{}{
var rw sync.Mutex
rw.Lock()
defer rw.Unlock()
if nil == InstanceMap{
InstanceMap = make(map[string]interface{})
}
return InstanceMap
}
func LockInstanceMap(k string,v interface{})error{
var rw sync.Mutex
rw.Lock()
defer rw.Unlock()
InstanceMap = GetInstanceMap()
if InstanceMap[k] == nil{
InstanceMap[k] = v
return nil
}else{
beego.Error("该 k = " + k + " 存在 v = ",v)
return errors.New("该 k = " + k + " 存在 v" )
}
}
func UnlockInstanceMap(k string){
var rw sync.Mutex
rw.Lock()
defer rw.Unlock()
InstanceMap = GetInstanceMap()
InstanceMap[k] = nil
}
func GetKeyInstanceMap(k string)interface{}{
var rw sync.Mutex
rw.Lock()
defer rw.Unlock()
InstanceMap = GetInstanceMap()
v := InstanceMap[k]
return v
}
2> 上面这种方法还是有问题,当程序包部署两个地方,a的动作之后加锁,b接收到了a完成的动作,没办法解开map的锁,name基于客户端的缓存,此方法后续再讲