百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

Go操作etcd(go操作docker实现沙箱)

liuian 2025-05-08 02:47 61 浏览

Go语言操作etcd,这里推荐官方包etcd/clientv3。 文档:
https://pkg.go.dev/go.etcd.io/etcd/clientv3 etcd v3使用gRPC进行远程过程调用。和clientv3使用grpc-go连接到etcd。确保在使用客户端后关闭该客户端。如果客户端未关闭,连接将有泄漏的程序。若要指定客户端请求超时,请传递上下文,设置context.WithTimeout。

安装

go get go.etcd.io/etcd/client/v3

put、get操作

示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"
    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }

    defer cli.Close()

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    _,err = cli.Put(ctx, "testkey", "testvalues")
    cancel()
    if err != nil {
        // handle error!
        fmt.Printf("put操作失败%v\n",err)
    }


    ctx, cancel = context.WithTimeout(context.Background(), time.Second)
    resp, err := cli.Get(ctx, "testkey")
    cancel()
    if err != nil {
        // handle error!
        fmt.Printf("get操作失败%v\n",err)
    }
    // use the response
    fmt.Println(resp)
    for _, kv := range resp.Kvs {
        fmt.Printf("%s,%s",kv.Key,kv.Value)
    }

}

watch 操作

watch监控某个key的变化 示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"
    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }
    defer cli.Close()
    rch := cli.Watch(context.Background(), "testkey")
    for wresp := range rch {
        for _, ev := range wresp.Events {
            fmt.Printf("%s %q : %q\n", ev.Type, ev.Kv.Key, ev.Kv.Value)
        }
    }

}

可在修改testkey值,观察其变化

删除

示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"
    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }
    defer cli.Close()

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    resp, err := cli.Delete(ctx, "testkey")
    cancel()
    if err != nil {
        // handle error!
        fmt.Printf("delete操作失败%v\n",err)
    }
    fmt.Println(resp.Deleted) //是否被删除
}

lease租约

示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"

    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }
    defer cli.Close()
    //设置租约为5秒
    resp, err := cli.Grant(context.TODO(), 5)
    if err != nil {
        fmt.Printf("设置lease失败%v\n",err)
    }

    // 5秒后 ‘foo’ 将被移除
    r, err := cli.Put(context.TODO(), "foo", "bar", clientv3.WithLease(resp.ID))
    if err != nil {
        fmt.Printf("lease失败%v\n",err)
    }
    fmt.Println(r.OpResponse())
}

keep-alive查看租约是否存活

示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"
    "log"

    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }
    defer cli.Close()
    //设置租约为5秒
    resp, err := cli.Grant(context.TODO(), 5)
    if err != nil {
        fmt.Printf("设置lease失败%v\n",err)
    }

    // 5秒后 ‘foo’ 将被移除
    r, err := cli.Put(context.TODO(), "foo", "bar", clientv3.WithLease(resp.ID))
    if err != nil {
        fmt.Printf("lease失败%v\n",err)
    }
    fmt.Println(r.OpResponse())
    // the key 'foo' will be kept forever
    ch, kaerr := cli.KeepAlive(context.TODO(), resp.ID)
    if kaerr != nil {
        log.Fatal(kaerr)
    }

    ka := <-ch
    fmt.Println("ttl:", ka.TTL)

}

基于etcd实现分布式锁

示例

package main

import (
    "context"
    "fmt"
    clientv3 "go.etcd.io/etcd/client/v3"
    "go.etcd.io/etcd/client/v3/concurrency"

    "time"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"localhost:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        // handle error!
        fmt.Printf("连接etcd失败%v\n",err)
    }
    defer cli.Close()
    //为演示竞争锁,创建两个会话
    s1, err := concurrency.NewSession(cli)
    if err != nil {
        fmt.Println(err)
    }
    defer s1.Close()
    m1 := concurrency.NewMutex(s1, "/my-lock/")

    s2, err := concurrency.NewSession(cli)
    if err != nil {
        fmt.Println(err)
    }
    defer s2.Close()
    m2 := concurrency.NewMutex(s2, "/my-lock/")

    // s1获取锁
    if err := m1.Lock(context.TODO()); err != nil {
        fmt.Println(err)
    }
    fmt.Println("s1获取锁")

    m2Locked := make(chan struct{})
    go func() {
        defer close(m2Locked)
        // 等待s1释放锁 /my-lock/
        if err := m2.Lock(context.TODO()); err != nil {
            fmt.Println(err)
        }
    }()

    if err := m1.Unlock(context.TODO()); err != nil {
        fmt.Println(err)
    }
    fmt.Println("s1释放锁")

    <-m2Locked
    fmt.Println("s2获取锁")
}

etcd分布式锁和redis实现分布式锁的对比:

redis

优点:基于主从同步和哨兵实现,具有高可用 基于内存,读写速度快高性能

缺点:

  • 存在死锁问题,业务逻辑出错或超时等原因,没有及时释放锁,出现死锁。
  • 锁过期时间设置不合理,导致大量锁竞争。

etcd

  • 原子性 etcd是基于raft实现的,具有强一致性的kv存储。
  • 高性能 每个节点都可以处理大量的读写请求。
  • 可扩展性 可以增加节点扩容。
  • 高可用性 节点冗余,单节点出故障,不影响整个集群。

缺点:

  • 集群的配置相对复杂



相关推荐

驱动网卡(怎么从新驱动网卡)
驱动网卡(怎么从新驱动网卡)

网卡一般是指为电脑主机提供有线无线网络功能的适配器。而网卡驱动指的就是电脑连接识别这些网卡型号的桥梁。网卡只有打上了网卡驱动才能正常使用。并不是说所有的网卡一插到电脑上面就能进行数据传输了,他都需要里面芯片组的驱动文件才能支持他进行数据传输...

2026-01-30 00:37 liuian

win10更新助手装系统(微软win10更新助手)

1、点击首页“系统升级”的按钮,给出弹框,告诉用户需要上传IMEI码才能使用升级服务。同时给出同意和取消按钮。华为手机助手2、点击同意,则进入到“系统升级”功能华为手机助手华为手机助手3、在检测界面,...

windows11专业版密钥最新(windows11专业版激活码永久)

 Windows11专业版的正版密钥,我们是对windows的激活所必备的工具。该密钥我们可以通过微软商城或者通过计算机的硬件供应商去购买获得。获得了windows11专业版的正版密钥后,我...

手机删过的软件恢复(手机删除过的软件怎么恢复)
手机删过的软件恢复(手机删除过的软件怎么恢复)

操作步骤:1、首先,我们需要先打开手机。然后在许多图标中找到带有[文件管理]文本的图标,然后单击“文件管理”进入页面。2、进入页面后,我们将在顶部看到一行文本:手机,最新信息,文档,视频,图片,音乐,收藏,最后是我们正在寻找的[更多],单击...

2026-01-29 23:55 liuian

一键ghost手动备份系统步骤(一键ghost 备份)

  步骤1、首先把装有一键GHOST装系统的U盘插在电脑上,然后打开电脑马上按F2或DEL键入BIOS界面,然后就选择BOOT打USDHDD模式选择好,然后按F10键保存,电脑就会马上重启。  步骤...

怎么创建局域网(怎么创建局域网打游戏)

  1、购买路由器一台。进入路由器把dhcp功能打开  2、购买一台交换机。从路由器lan端口拉出一条网线查到交换机的任意一个端口上。  3、两台以上电脑。从交换机任意端口拉出网线插到电脑上(电脑设置...

精灵驱动器官方下载(精灵驱动手机版下载)

是的。驱动精灵是一款集驱动管理和硬件检测于一体的、专业级的驱动管理和维护工具。驱动精灵为用户提供驱动备份、恢复、安装、删除、在线更新等实用功能。1、全新驱动精灵2012引擎,大幅提升硬件和驱动辨识能力...

一键还原系统步骤(一键还原系统有哪些)

1、首先需要下载安装一下Windows一键还原程序,在安装程序窗口中,点击“下一步”,弹出“用户许可协议”窗口,选择“我同意该许可协议的条款”,并点击“下一步”。  2、在弹出的“准备安装”窗口中,可...

电脑加速器哪个好(电脑加速器哪款好)

我认为pp加速器最好用,飞速土豆太懒,急速酷六根本不工作。pp加速器什么网页都加速,太任劳任怨了!以上是个人观点,具体性能请自己试。ps:我家电脑性能很好。迅游加速盒子是可以加速电脑的。因为有过之...

任何u盘都可以做启动盘吗(u盘必须做成启动盘才能装系统吗)

是的,需要注意,U盘的大小要在4G以上,最好是8G以上,因为启动盘里面需要装系统,内存小的话,不能用来安装系统。内存卡或者U盘或者移动硬盘都可以用来做启动盘安装系统。普通的U盘就可以,不过最好U盘...

u盘怎么恢复文件(u盘文件恢复的方法)

开360安全卫士,点击上面的“功能大全”。点击文件恢复然后点击“数据”下的“文件恢复”功能。选择驱动接着选择需要恢复的驱动,选择接入的U盘。点击开始扫描选好就点击中间的“开始扫描”,开始扫描U盘数据。...

系统虚拟内存太低怎么办(系统虚拟内存占用过高什么原因)

1.检查系统虚拟内存使用情况,如果发现有大量的空闲内存,可以尝试释放一些不必要的进程,以释放内存空间。2.如果系统虚拟内存使用率较高,可以尝试增加系统虚拟内存的大小,以便更多的应用程序可以使用更多...

剪贴板权限设置方法(剪贴板访问权限)
剪贴板权限设置方法(剪贴板访问权限)

1、首先打开iphone手机,触碰并按住单词或图像直到显示选择选项。2、其次,然后选取“拷贝”或“剪贴板”。3、勾选需要的“权限”,最后选择开启,即可完成苹果剪贴板权限设置。仅参考1.打开苹果手机设置按钮,点击【通用】。2.点击【键盘】,再...

2026-01-29 21:37 liuian

平板系统重装大师(平板重装win系统)

如果你的平板开不了机,但可以连接上电脑,那就能好办,楼主下载安装个平板刷机王到你的个人电脑上,然后连接你的平板,平板刷机王会自动识别你的平板,平板刷机王上有你平板的我刷机包,楼主点击下载一个,下载完成...

联想官网售后服务网点(联想官网售后服务热线)

联想3c服务中心是联想旗下的官方售后,是基于互联网O2O模式开发的全新服务平台。可以为终端用户提供多品牌手机、电脑以及其他3C类产品的维修、保养和保险服务。根据客户需求层次,联想服务针对个人及家庭客户...