分布式鎖有三種
1.樂觀鎖
2.redis鎖
3.zookeeper鎖
這次進行一個設計,redis分布式鎖,只需要三種操作,增刪查
首先一個redis連接池,由於會被導入,所以init
import ( "redigo/redis" ) const ( SET_IF_NOT_EXIST = "NX" // 不存在則執行 SET_WITH_EXPIRE_TIME = "EX" // 過期時間(秒) PX 毫秒 SET_LOCK_SUCCESS = "OK" // 操作成功 DEL_LOCK_SUCCESS = 1 // lock 刪除成功 DEL_LOCK_NON_EXISTENT = 0 // 刪除lock key時,並不存在 ) var ( RdPool *redis.Pool Conn redis.Conn ) // NewRedisPool func init(){ pool := &redis.Pool{ Dial: func() (conn redis.Conn, e error) { return redis.Dial("tcp","localhost:6379") }, MaxIdle: 10, MaxActive: 20, IdleTimeout: 100, } RdPool = pool Conn = pool.Get() }
添加lock鎖
/* redis 類型 字符串設置一個分布式鎖 (哈希內部字段不支持過期判斷,redis只支持頂級key過期) @param key: 鎖名,格式為 用戶id_操作_方法 @param requestId: 客戶端唯一id 用來指定鎖不被其他線程(協程)刪除 @param ex: 過期時間 */ func AddLock(key,requestId string,ex int) bool { msg,_ := redis.String( Conn.Do("SET",key,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,ex), ) if msg == SET_LOCK_SUCCESS { return true } return false }
查
/* 獲得redis分布式鎖的值 @param key:redis類型字符串的key值 @param return: redis類型字符串的value */ func GetLock(key string) string { msg,_ := redis.String(Conn.Do("GET",key)) return msg }
刪
/* 刪除redis分布式鎖 @param key:redis類型字符串的key值 @param requestId: 唯一值id,與value值對比,避免在分布式下其他實例刪除該鎖 */ func DelLock(key ,requestId string) bool{ if GetLock(key) == requestId { msg,_ := redis.Int64(Conn.Do("DEL",key)) // 避免操作時間過長,自動過期時再刪除返回結果為0 if msg == DEL_LOCK_SUCCESS || msg == DEL_LOCK_NON_EXISTENT{ return true } return false } return false }
實際操作
package main import ( "fmt" "github.com/google/uuid" "./pool" ) func main() { uid, _ := uuid.NewUUID() id := uid.String() key := "用戶id001_操作del_操作方法名DelComment" if pool.AddLock(key, id, 3) { fmt.Println("添加lock成功") } else { fmt.Println("添加lock失敗") } if pool.GetLock(key) == id { fmt.Println("相等") }else { fmt.Println("不相等") } if pool.DelLock(key,id){ fmt.Println("刪除成功") } else { fmt.Println("刪除失敗") } }
實際結果
添加lock成功
相等
刪除成功
參考資料: