etcd之etcd分布式锁及事务(四)

1、etcd分布式锁及事务

1.1 前言

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如

果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥

来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。

1.2 etcd分布式锁设计

1、排他性:任意时刻,只能有一个机器的一个线程能获取到锁。

通过在etcd中存入key值来实现上锁,删除key实现解锁,参考下面伪代码:

func Lock(key string, cli *clientv3.Client) error {//获取key,判断是否存在锁resp, err := cli.Get(context.Background(), key)if err != nil {return err}//锁存在,返回上锁失败if len(resp.Kvs) > 0 {return errors.New("lock fail")}_, err = cli.Put(context.Background(), key, "lock")if err != nil {return err}return nil
}
//删除key,解锁
func UnLock(key string, cli *clientv3.Client) error {_, err := cli.Delete(context.Background(), key)return err
}

当发现已上锁时,直接返回lock fail。也可以处理成等待解锁,解锁后竞争锁。

//等待key删除后再竞争锁
func waitDelete(key string, cli *clientv3.Client) {rch := cli.Watch(context.Background(), key)for wresp := range rch {for _, ev := range wresp.Events {switch ev.Type {case mvccpb.DELETE: //删除return}}}
}

2、容错性:只要分布式锁服务集群节点大部分存活,client就可以进行加锁解锁操作。

etcd基于Raft算法,确保集群中数据一致性。

3、避免死锁:分布式锁一定能得到释放,即使client在释放之前崩溃。

上面分布式锁设计有缺陷,假如client获取到锁后程序直接崩了,没有解锁,那其他线程也无法拿到锁,导致死锁

出现。

通过给key设定leases来避免死锁,但是leases过期时间设多长呢?假如设了30秒,而上锁后的操作比30秒

大,会导致以下问题:

  • 操作没完成,锁被别人占用了,不安全

  • 操作完成后,进行解锁,这时候把别人占用的锁解开了

解决方案:给key添加过期时间后,以Keep leases alive方式延续leases,当client正常持有锁时,锁不会过

期;当client程序崩掉后,程序不能执行Keep leases alive,从而让锁过期,避免死锁。看以下伪代码:

//上锁
func Lock(key string, cli *clientv3.Client) error {//获取key,判断是否存在锁resp, err := cli.Get(context.Background(), key)if err != nil {return err}//锁存在,等待解锁后再竞争锁if len(resp.Kvs) > 0 {waitDelete(key, cli)return Lock(key)}//设置key过期时间resp, err := cli.Grant(context.TODO(), 30)if err != nil {return err}//设置key并绑定过期时间_, err = cli.Put(context.Background(), key, "lock", clientv3.WithLease(resp.ID))if err != nil {return err}//延续key的过期时间_, err = cli.KeepAlive(context.TODO(), resp.ID)if err != nil {return err}return nil
}
//通过让key值过期来解锁
func UnLock(resp *clientv3.LeaseGrantResponse, cli *clientv3.Client) error {_, err := cli.Revoke(context.TODO(), resp.ID)return err
}

经过以上步骤,我们初步完成了分布式锁设计。其实官方已经实现了分布式锁,它大致原理和上述有出入,接下来

我们看下如何使用官方的分布式锁。

1.3 etcd分布式锁使用

package mainimport ("context""fmt""github.com/coreos/etcd/clientv3""github.com/coreos/etcd/clientv3/concurrency""log"
)var endpoints = []string{"localhost:2379"}func ExampleMutex_Lock() {cli, err := clientv3.New(clientv3.Config{Endpoints: endpoints})if err != nil {log.Fatal(err)}defer cli.Close()// create two separate sessions for lock competitions1, err := concurrency.NewSession(cli)if err != nil {log.Fatal(err)}defer s1.Close()m1 := concurrency.NewMutex(s1, "/my-lock/")s2, err := concurrency.NewSession(cli)if err != nil {log.Fatal(err)}defer s2.Close()m2 := concurrency.NewMutex(s2, "/my-lock/")// acquire lock for s1if err := m1.Lock(context.TODO()); err != nil {log.Fatal(err)}fmt.Println("acquired lock for s1")m2Locked := make(chan struct{})go func() {defer close(m2Locked)// wait until s1 is locks /my-lock/if err := m2.Lock(context.TODO()); err != nil {log.Fatal(err)}}()if err := m1.Unlock(context.TODO()); err != nil {log.Fatal(err)}fmt.Println("released lock for s1")<-m2Lockedfmt.Println("acquired lock for s2")
}func main() {ExampleMutex_Lock()
}
# 输出
acquired lock for s1
released lock for s1
acquired lock for s2

此代码来源于官方文档,etcd分布式锁使用起来很方便。

1.4 etcd事务

顺便介绍一下etcd事务,先看这段伪代码:

Txn(context.TODO()).If(//如果以下判断条件成立Compare(Value(k1), "<", v1),Compare(Version(k1), "=", 2)
).Then(//则执行Then代码段OpPut(k2,v2), OpPut(k3,v3)
).Else(//否则执行Else代码段OpPut(k4,v4), OpPut(k5,v5)
).Commit()//最后提交事务
package mainimport ("context""fmt""github.com/coreos/etcd/clientv3""log""time"
)var endpoints = []string{"localhost:2379"}func ExampleKV_txn() {cli, err := clientv3.New(clientv3.Config{Endpoints:   endpoints,DialTimeout: 5 * time.Second,})if err != nil {log.Fatal(err)}defer cli.Close()kvc := clientv3.NewKV(cli)_, err = kvc.Put(context.TODO(), "key", "xyz")if err != nil {log.Fatal(err)}ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)_, err = kvc.Txn(ctx).// txn value comparisons are lexicalIf(clientv3.Compare(clientv3.Value("key"), ">", "abc")).// the "Then" runs, since "xyz" > "abc"Then(clientv3.OpPut("key", "XYZ")).// the "Else" does not runElse(clientv3.OpPut("key", "ABC")).Commit()cancel()if err != nil {log.Fatal(err)}gresp, err := kvc.Get(context.TODO(), "key")cancel()if err != nil {log.Fatal(err)}for _, ev := range gresp.Kvs {fmt.Printf("%s : %s\n", ev.Key, ev.Value)}
}func main() {ExampleKV_txn()
}
# 输出
key : XYZ

上面的使用例子,代码来自官方文档。

1.5 总结

如果发展到分布式服务阶段,且对数据的可靠性要求很高,选etcd实现分布式锁不会错。一般的Redis分布式

锁,可能出现锁丢失的情况(如果你是Java开发者,可以使用Redisson客户端实现分布式锁,据说不会出现锁丢

失的情况)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458385.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu-开机黑屏问题快速解决方法

开机黑屏一般是由于显卡驱动出现问题导致。 快速解决方法&#xff1a; 通过ubuntu高级选项->recovery模式->resume->按esc即可进入recovery模式&#xff0c;进去后重装显卡驱动&#xff0c;重启即可解决。附加问题&#xff1a;ubuntu的默认显示管理器是gdm3,如果重…

海洋生物图像分割系统:算法改进策略

海洋生物图像分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-DiverseBranchBlock&#xff06;yolov8-seg-C2f-Faster-EMA等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目…

PHP-FPM 性能配置优化

4 核 8 G 服务器大约可以开启 500 个 PHP-FPM&#xff0c;极限吞吐量在 580 qps &#xff08;Query Per Second 每秒查询数&#xff09;左右。 Nginx php-fpm 是怎么工作的&#xff1f; php-fpm 全称是 PHP FastCGI Process Manager 的简称&#xff0c;从名字可得知&#xff…

第十七周:机器学习

目录 摘要 Abstract 一、MCMC 1、马尔科夫链采样 step1 状态设定 step2 转移矩阵 step3 马尔科夫链的生成 step4 概率分布的估计 2、蒙特卡洛方法 step1 由一个分布产生随机变量 step2 用这些随机变量做实验 3、MCMC算法 4、参考文章 二、flow-based GAN 1、引…

【Linux网络】Linux网络基础入门:初识网络,理解网络协议

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux网络 &#x1f4d2;1. 计算机网络背景发展历程"协议" &#x1f4dc;2. 网络协…

UML外卖系统报告(包含具体需求分析)

1、系统背景 随着互联网技术的快速发展&#xff0c;外卖订餐服务逐渐成为人们生活中的一部分。传统的电话订餐方式面临诸多不便和限制&#xff0c;而基于互联网的外卖订餐系统则提供了更加便捷、快速和高效的订餐服务。这种系统通过将餐厅、顾客和配送人员连接起来&#xff0c…

Sentinel详解

参考博客&#xff1a; SpringCloud Sentinel集成到微服务项目中&#xff08;保姆级教程&#xff09; 什么是Sentinel Sentinel 是面向分布式服务架构的轻量级流量控制产品&#xff0c;主要以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度来保护服务…

Vue学习记录之二十五 Vue3中Web Componets的使用

一、webcomponets介绍 在Vue 3中使用Web Components可以通过多种方式实现。Web Components是一组允许你创建可重用、封装良好的自定义元素的标准技术。它们包括Custom Elements、Shadow DOM、HTML Templates等。 Vue3 支持原生模式&#xff0c;可以让单个文件的js,css,html以h…

移植rv1106SDK的ipcweb到ubuntu

移植minilogger 在sdk中找到minilogger&#xff0c;复制到任意的文件夹&#xff0c;执行 cmake ./ make make install把minilogger 安装到系统 修改Makefile 在上次那个基础上&#xff0c;修改Makefile #* 这里原来要包含../Makefile.param&#xff0c;但含有sdk的很多参数…

w003基于Springboot的图书个性化推荐系统的设计与实现

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Mysql(十) --- 用户权限和管理

文章目录 前言1. 应用场景2.用户2.1. 查看用户2.2. 创建用户2.2.1 语法2.2.2. 注意事项 2.2.3.示例2.3. 修改密码2.3.1. 语法2.3.2. 示例 2.4.删除用户2.4.1.语法2.4.2.示例 3. 权限和授权MySQL内置支持的权限列表3.1.给用户授权3.1.1.语法3.1.2. 示例 3.2.回收权限3.2.1.语法3…

Golang Agent 可观测性的全面升级与新特性介绍

作者&#xff1a;张海彬&#xff08;古琦&#xff09; 背景 自 2024 年 6 月 26 日&#xff0c;ARMS 发布了针对 Golang 应用的可观测性监控功能以来&#xff0c;阿里云 ARMS 团队与程序语言与编译器团队一直致力于不断优化和提升该系统的各项功能&#xff0c;旨在为开发者提…

基于SpringBoot的中药材进存销管理系统设计与实现

摘要 中药材进存销管理系统是为了满足中药材生产和销售企业的高效管理需求&#xff0c;涵盖了药材采购、库存管理和销售跟踪等主要功能。本系统采用Spring Boot框架进行开发&#xff0c;结合了前端和数据库设计&#xff0c;构建了一个实用的中药材管理平台&#xff0c;为企业提…

游戏服务器被攻击有办法防护吗

游戏服务器受到攻击时比较常见的。就算是刚上线的游戏&#xff0c;都会有被攻击的时候。游戏服务器受到攻击的原因以及解决方案有哪些呢&#xff1f; 游戏服务器被攻击的原因有哪些呢&#xff1f; 1、常见的攻击&#xff0c;大部分来自于同行之间的恶意竞争&#xff0c;你的游…

【QT】Qt窗口(上)

个人主页~ Qt窗口 一、菜单栏二、工具栏三、状态栏四、浮动窗口 Qt窗口是通过QMainWindow类来实现的&#xff0c;我们之前的学习是通过QWidget类实现的 QMainWindow包含一个菜单栏Menu Bar②&#xff0c;多个工具栏Tool Bars③&#xff0c;多个浮动窗口Dock Widgets&#xff0c…

OpenRTP 传输增加OpenRTPServer

开源地址 最近增加了OpenRTPServer&#xff0c; 已经修改完成一版放在了目录下&#xff0c;window和linux下编译都成功了&#xff0c;不过由于修改代码CMakefile 需要修改&#xff0c;先放放 OpenRTP开源地址 vlc得纠错传输方式 我发现我代码写错以后&#xff0c;vlc 依然能…

大数据Azkaban(二):Azkaban简单介绍

文章目录 Azkaban简单介绍 一、Azkaban特点 二、Azkaban组成结构 三、Azkaban部署模式 1、solo-server ode&#xff08;独立服务器模式&#xff09; 2、two server mode&#xff08;双服务器模式&#xff09; 3、distributed multiple-executor mode&#xff08;分布式多…

【Rust】环境搭建

▒ 目录 ▒ &#x1f6eb; 导读需求 1️⃣ 安装Chocolatey安装依赖 2️⃣ 安装RustRover安装toolchain&#xff08;rustup、VS&#xff09;重启配置生效设置安装插件 &#x1f4d6; 参考资料 &#x1f6eb; 导读 需求 重装系统&#xff0c;记录下环境搭建遇到的问题。 1️⃣ …

【最全基础知识2】机器视觉系统硬件组成之工业相机镜头篇--51camera

机器视觉系统中,工业镜头作为必备的器件之一,须和工业相机搭配。工业镜头是机器视觉系统中不可或缺的重要组成部分,其质量和性能直接影响到整个系统的成像质量和检测精度。 目录 一、基本功能和作用 二、分类 1、按成像方式分 2、按焦距分 3、按接口类型分 4、按应用…

如何制定有效的学习计划

文章目录 第一章&#xff1a;目标设定1.1 目标的重要性1.2 SMART原则1.3 目标设定公式 第二章&#xff1a;时间管理2.1 时间的重要性2.2 制定时间表2.3 时间管理公式2.4 番茄工作法2.5 时间分配公式 第三章&#xff1a;学习策略3.1 学习方法3.2 学习材料的选择3.3 学习效果公式…