鎖的作用是:當(dāng)多個(gè)線程競(jìng)爭(zhēng)一個(gè)資源時(shí),會(huì)出現(xiàn)資源被干掉或者資源重置為另一個(gè)值,這時(shí)鎖的作用就出現(xiàn)了,鎖住當(dāng)前的資源,其他線程就不會(huì)修改此數(shù)據(jù)了。
使用redis鎖的思想是:將資源作為一個(gè)獨(dú)立標(biāo)識(shí),然后放在字符串里面,并且使用過(guò)期時(shí)間來(lái)聲明鎖:
也可以手動(dòng)釋放,才去循環(huán)設(shè)置超時(shí)時(shí)間
SetNX 這個(gè)命令就很好地作為資源聲明,創(chuàng)建一個(gè)鎖:
import (
"context"
"go-redis/client"
"time"
"github.com/go-redis/redis/v8"
"github.com/google/uuid"
)
var ctx = context.TODO()
func Lock(lockname string, locktime int64) string {
u, _ := uuid.NewUUID()
ustr := u.String()
end := time.Now().Unix() + locktime
for {
? if time.Now().Unix() < end {
? client.RedisClient().SetNX(ctx, "lock:"+lockname, ustr, time.Hour)
? return ustr
? }
}
}
而釋放鎖,一般是兩步合并的操作,因?yàn)樗鼤?huì)減少IO操作。
兩步分為:
獲取資源
如果有此資源,釋放鎖(刪除資源uuid)
package redislock
import (
"context"
"go-redis/client"
"time"
"github.com/go-redis/redis/v8"
"github.com/google/uuid"
)
var ctx = context.TODO()
// 釋放鎖
func Release(lockname string, indetifier string) bool {
pipline := client.RedisClient().TxPipeline()
lockname = "lock:" + lockname
for {
? pipline.Get(ctx, lockname).Val()
? cmders, _ := pipline.Exec(ctx)
? perm, _ := cmders[0].(*redis.StringCmd).Result()
? if perm == indetifier {
? pipline.Del(ctx, lockname) // 刪除鎖
? pipline.Exec(ctx)
? return true
? }
}
}