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