parent
efa2675704
commit
88afe3db07
@ -0,0 +1,76 @@
|
||||
package golock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.etcd.io/etcd/client/v3"
|
||||
)
|
||||
|
||||
type LockEtcd struct {
|
||||
etcdClient *clientv3.Client // 驱动
|
||||
}
|
||||
|
||||
func NewLockEtcd(etcdClient *clientv3.Client) *LockEtcd {
|
||||
return &LockEtcd{etcdClient: etcdClient}
|
||||
}
|
||||
|
||||
// Lock 上锁
|
||||
// key 锁名
|
||||
// val 锁内容
|
||||
// ttl 锁过期时间
|
||||
func (e *LockEtcd) Lock(key string, val string, ttl int64) (string, error) {
|
||||
if ttl <= 0 {
|
||||
return "", errors.New("长期请使用 LockForever 方法")
|
||||
}
|
||||
// 1、获取
|
||||
get, err := e.etcdClient.Get(context.Background(), key)
|
||||
if err != nil {
|
||||
return "", errors.New("获取异常")
|
||||
}
|
||||
if len(get.Kvs) > 0 {
|
||||
return "", errors.New("上锁失败,已存在")
|
||||
}
|
||||
// 2、申请一个lease(租约)
|
||||
lease := clientv3.NewLease(e.etcdClient)
|
||||
// 3、申请一个*秒的租约
|
||||
leaseGrantResp, err := lease.Grant(context.TODO(), ttl)
|
||||
if err != nil {
|
||||
return "", errors.New(fmt.Sprintf("申请租约失败 %s", err))
|
||||
}
|
||||
// 5、获得kv api子集
|
||||
kv := clientv3.NewKV(e.etcdClient)
|
||||
// 4、设置
|
||||
kv.Put(context.TODO(), key, val, clientv3.WithLease(leaseGrantResp.ID))
|
||||
if err != nil {
|
||||
return "", errors.New("上锁失败")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Unlock 解锁
|
||||
// key 锁名
|
||||
func (e *LockEtcd) Unlock(key string) error {
|
||||
_, err := e.etcdClient.Delete(context.Background(), key)
|
||||
return err
|
||||
}
|
||||
|
||||
// LockForever 永远上锁
|
||||
// key 锁名
|
||||
// val 锁内容
|
||||
func (e *LockEtcd) LockForever(key string, val string) (string, error) {
|
||||
// 1、获取
|
||||
get, err := e.etcdClient.Get(context.Background(), key)
|
||||
if err != nil {
|
||||
return "", errors.New("获取异常")
|
||||
}
|
||||
if len(get.Kvs) > 0 {
|
||||
return "", errors.New("上锁失败,已存在")
|
||||
}
|
||||
// 2、设置
|
||||
e.etcdClient.Put(context.TODO(), key, val)
|
||||
if err != nil {
|
||||
return "", errors.New("上锁失败")
|
||||
}
|
||||
return val, nil
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package golock
|
||||
|
||||
type Lock struct {
|
||||
c chan struct{}
|
||||
}
|
||||
|
||||
func NewLock() Lock {
|
||||
l := Lock{}
|
||||
l.c = make(chan struct{}, 1)
|
||||
l.c <- struct{}{}
|
||||
return l
|
||||
}
|
||||
|
||||
// Lock 上锁
|
||||
func (l *Lock) Lock() bool {
|
||||
lockResult := false
|
||||
select {
|
||||
case <-l.c:
|
||||
lockResult = true
|
||||
default:
|
||||
}
|
||||
return lockResult
|
||||
}
|
||||
|
||||
// Unlock 解锁
|
||||
func (l *Lock) Unlock() {
|
||||
l.c <- struct{}{}
|
||||
}
|
@ -1,46 +1,67 @@
|
||||
package golock
|
||||
|
||||
import (
|
||||
"go.dtapp.net/library/utils/dorm"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ConfigLockRedis struct {
|
||||
Key string
|
||||
KeyContent string
|
||||
ExpirationTime time.Duration
|
||||
}
|
||||
|
||||
type LockRedis struct {
|
||||
config ConfigLockRedis
|
||||
db *dorm.RedisClient
|
||||
redisClient *redis.Client // 驱动
|
||||
}
|
||||
|
||||
func NewLockRedis(db *dorm.RedisClient) *LockRedis {
|
||||
return &LockRedis{db: db}
|
||||
func NewLockRedis(redisClient *redis.Client) *LockRedis {
|
||||
return &LockRedis{redisClient: redisClient}
|
||||
}
|
||||
|
||||
// Lock 上锁
|
||||
func (lockRedis *LockRedis) Lock() bool {
|
||||
judgeCache := lockRedis.db.NewStringOperation().Get(lockRedis.config.Key).UnwrapOr("")
|
||||
if judgeCache != "" {
|
||||
return true
|
||||
// key 锁名
|
||||
// val 锁内容
|
||||
// ttl 锁过期时间
|
||||
func (r *LockRedis) Lock(key string, val string, ttl int64) (string, error) {
|
||||
if ttl <= 0 {
|
||||
return "", errors.New("长期请使用 LockForever 方法")
|
||||
}
|
||||
// 1、获取
|
||||
get, err := r.redisClient.Get(context.Background(), key).Result()
|
||||
if err != nil {
|
||||
return "", errors.New("获取异常")
|
||||
}
|
||||
if get != "" {
|
||||
return "", errors.New("上锁失败,已存在")
|
||||
}
|
||||
lockRedis.db.NewStringOperation().Set(lockRedis.config.Key, lockRedis.config.KeyContent, dorm.WithExpire(lockRedis.config.ExpirationTime))
|
||||
return true
|
||||
// 2、设置
|
||||
err = r.redisClient.Set(context.Background(), key, val, time.Duration(ttl)).Err()
|
||||
if err != nil {
|
||||
return "", errors.New("上锁失败")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Unlock Lock 解锁
|
||||
func (lockRedis *LockRedis) Unlock() {
|
||||
lockRedis.db.NewStringOperation().Del(lockRedis.config.Key)
|
||||
// Unlock 解锁
|
||||
// key 锁名
|
||||
func (r *LockRedis) Unlock(key string) error {
|
||||
_, err := r.redisClient.Del(context.Background(), key).Result()
|
||||
return err
|
||||
}
|
||||
|
||||
// LockForever 永远上锁
|
||||
func (lockRedis *LockRedis) LockForever() bool {
|
||||
judgeCache := lockRedis.db.NewStringOperation().Get(lockRedis.config.Key).UnwrapOr("")
|
||||
if judgeCache != "" {
|
||||
return true
|
||||
// key 锁名
|
||||
// val 锁内容
|
||||
func (r *LockRedis) LockForever(key string, val string) (string, error) {
|
||||
// 1、获取
|
||||
get, err := r.redisClient.Get(context.Background(), key).Result()
|
||||
if err != nil {
|
||||
return "", errors.New("获取异常")
|
||||
}
|
||||
if get != "" {
|
||||
return "", errors.New("上锁失败,已存在")
|
||||
}
|
||||
// 2、设置
|
||||
err = r.redisClient.Set(context.Background(), key, val, 0).Err()
|
||||
if err != nil {
|
||||
return "", errors.New("上锁失败")
|
||||
}
|
||||
lockRedis.db.NewStringOperation().Set(lockRedis.config.Key, lockRedis.config.KeyContent)
|
||||
return true
|
||||
return val, nil
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package golock
|
Loading…
Reference in new issue