在 go 框架中,完成分布式锁有以下两种方式:etcd:运用 etcd 的 watch 特点,当锁被释放时触发事件通告,完成分布式锁。redis:应用 redis 的 setnx 和 expire 指令,完成简易可靠的分布式锁。
内容来自samhan
Go 架构完成分布式锁在分布式系统中,需要确保不同服务或过程访问共享资源时顺序浏览,此时就需要应用分布式锁。在 Go 框架中,几个流行的库能够实现分布式锁,如分布式融洽服务 Etcd 和分布式 KV 数据库 Redis。
内容来自zvvq
EtcdEtcd 是一个分布式、高可用的键值存放,适合于完成分布式锁。Etcd 的锁机制通过运用其 Watch 特点,当锁被释放时触发事件通告。
zvvq好,好zvvq
//import"github.com/coreos/etcd/clientv3" copyright zvvq
//EtcdLock完成了分布式锁 本文来自zvvq
type EtcdLock struct { 本文来自zvvq
client clientv3.Client 内容来自zvvq,别采集哟
key string
copyright zvvq
}
copyright zvvq
// NewEtcdLock 创建一个EtcdLock zvvq.cn
func NewEtcdLock(client clientv3.Client, key string) EtcdLock {
return &EtcdLock{
zvvq.cn
client: client,
内容来自zvvq
key: key, 内容来自zvvq
}
内容来自zvvq
}
// Lock 试着获得锁
内容来自zvvq
func (l EtcdLock) Lock() error {
本文来自zvvq
ctx := context.Background()
lease, err := l.client.Grant(ctx, 10) // 租期时间为10秒 内容来自zvvq
if err != nil {
copyright zvvq
return err
} 内容来自zvvq,别采集哟
txn := l.client.Txn(ctx).If(
clientv3.Compare(clientv3.Value(l.key), "=", ""),
zvvq
).Then(
clientv3.OpPut(l.key, "locked", clientv3.WithLease(lease.ID)), copyright zvvq
) zvvq.cn
resp, err := txn.Commit() 内容来自zvvq
if err != nil { zvvq
return err
copyright zvvq
}
zvvq.cn
if resp.Succeeded { 内容来自samhan666
return nil
}
return errors.New("获得锁失败")
} zvvq好,好zvvq
// Unlock 释放锁
func (l EtcdLock) Unlock() error { 内容来自zvvq
ctx := context.Background()
内容来自zvvq
_, err := l.client.Delete(ctx, l.key)
return err 内容来自zvvq,别采集哟
}
内容来自samhan
RedisRedis 是一种分布式 KV 数据库,还支持分布式锁的完成。Redis 带来了 SETNX 和 EXPIRE 指令,可用于完成简易可靠的锁。 zvvq好,好zvvq
//import"github.com/go-redis/redis/v8" 本文来自zvvq
// RedisLock完成了分布式锁 内容来自zvvq
type RedisLockstruct{ copyright zvvq
clientredis.Client 内容来自zvvq,别采集哟
keystring zvvq好,好zvvq
}
//NewRedisLock创建一个RedisLock 本文来自zvvq
func NewRedisLock(client redis.Client, key string) RedisLock { copyright zvvq
return &RedisLock{ 内容来自zvvq
client: client,
zvvq
key: key,
内容来自zvvq
}
zvvq
} 本文来自zvvq
// Lock 试着获得锁 zvvq好,好zvvq
func (l RedisLock) Lock() error { zvvq
ctx := context.Background()
zvvq
res, err := l.client.SetNX(ctx, l.key, "locked", 10time.Second).Result() // 锁10秒 内容来自samhan666
if err != nil {
return err
内容来自samhan666
} zvvq
if !res {
return errors.New("获得锁失败")
} zvvq
return nil
内容来自samhan666
}
copyright zvvq
// Unlock 释放锁 内容来自zvvq
func (l RedisLock) Unlock() error { 内容来自zvvq,别采集哟
ctx := context.Background() copyright zvvq
_, err := l.client.Del(ctx, l.key).Result() zvvq好,好zvvq
return err
} 内容来自samhan666
实战案例考虑一个场景,多个微服务共享一个数据库连接池,为了避免并发浏览造成数据库连接被耗光,必须对连接池开展分布式锁操纵。
lock:=NewEtcdLock(client,"db-pool-lock")
内容来自samhan
iferr:=lock.Lock();err!=nil{ 内容来自zvvq
log.Fatalf("获得锁失败: %v", err) 内容来自zvvq
} 内容来自samhan666
// 浏览数据库连接池...
内容来自samhan
if err := lock.Unlock(); err != nil { 本文来自zvvq
log.Fatalf("释放锁失败: %v", err)
}
以上就是golang架构如何做到分布式锁?的详细内容,大量请关注其他类似文章! 内容来自samhan666