ETCD概述--使用/特性/架构/原理

ETCD概述

请添加图片描述
ETCD是一个高度一致的分布式键值存储, 它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据(高可用, 强一致性)​全局的配置服务中心. 本文将介绍其特性、相关操作和常见的应用场景.

如果想了解更多, 请查阅我的技术博客: https://dingyuqi.com

特性

不能存储大量的具体数据, 应用来存储少量重要的数据

相关操作

$ etcdctl put foo bar
OK

​在HTTP请求体中的JSON对象, 其包含的key和value字段都被定义成了byte数组, 因此必须在JSON对象中, 使用base64编码对内容进行处理

$ etcdctl get foo
foo
bar

这是只读取键 foo 的值的命令:

$ etcdctl get foo --print-value-only
bar

键 foo 到foo3的值的命令:

$ etcdctl get foo foo3
foo
bar
foo1
bar1
foo2
bar2
### 半开区间 [foo, foo3)

范围覆盖以 foo 为前缀的所有键的命令, 结果数量限制为2:

$ etcdctl get --prefix --limit=2 foo
foo
bar
foo1
bar1

$ etcdctl get key -w json

版本(revision)

每put一次相同的key都会修改该key的版本

$ etcdctl get --prefix foo # 访问键的最新版本
foo
bar_new
foo1
bar1_new

$ etcdctl get --prefix --rev=4 foo # 访问修订版本为 4 时的键的版本
foo
bar_new
foo1
bar1

$ etcdctl get --prefix --rev=3 foo # 访问修订版本为 3 时的键的版本
foo
bar
foo1
bar1

$ etcdctl get --prefix --rev=2 foo # 访问修订版本为 2 时的键的版本
foo
bar

$ etcdctl get --prefix --rev=1 foo # 访问修订版本为 1 时的键的版本

观察(watch)

watch key

观察多个键 foozoo 的命令:

$ etcdctl watch -i
$ watch foo
$ watch zoo
# 在另外一个终端: etcdctl put foo bar
PUT
foo
bar
# 在另外一个终端: etcdctl put zoo val
del
zoo
val

观察历史改动:

# 从修订版本 2 开始观察键 `foo` 的改动
$ etcdctl watch --rev=2 foo
PUT
foo
bar
PUT
foo
bar_new

租约(lease)

一个lease可对应多个key

授予租约:

# 授予租约, TTL为10秒
$ etcdctl lease grant 10
lease 32695410dcc0ca06 granted with TTL(10s)

# 附加键 foo 到租约32695410dcc0ca06
$ etcdctl put --lease=32695410dcc0ca06 foo bar
OK

撤销一个租约(会删除附带lease的的所所有key):

$ etcdctl lease revoke 32695410dcc0ca06
lease 32695410dcc0ca06 revoked

$ etcdctl get foo
# 空应答, 因为租约撤销导致foo被删除

续约(刷新)

$ etcdctl lease keep-alive 32695410dcc0ca06
lease 32695410dcc0ca06 keepalived with TTL(10)
lease 32695410dcc0ca06 keepalived with TTL(10)
lease 32695410dcc0ca06 keepalived with TTL(10)

事务:

$ etcdctl txn -i
compares:  # 比较
value("key") = "xxx"  # key具体值
create("key") = "xxx"  # key的版本信息
mod("key") = "xxx"  # key的修改版本
# 可写多个
例如: (事务相当于一个if-else)
$ etcdctl txn -i
compares:
value("foo") = "ccvvb"

success requests (get, put, del):
get foo

failure requests (get, put, del):
del foo

SUCCESS

foo
ccvvb

应用场景

共享配置(kv存储)

​有一个定义良好、面向用户的API(gRPC), 有些语言的客户端不支持gRPC通信协议, 此时就可以使用gRPC-Gateway对外提供的HTTP API接口, 通过HTTP请求, 实现与gRPC调用协议同样的功能

服务注册与发现

​服务注册是指服务实例启动时将自身信息注册到服务注册与发行中心, 并在运行时通过心跳等方式向其汇报自身服务状态

​服务发现是指服务实例向服务注册与发现中心获取其他服务实例信息, 用于远程调用

​服务注册与发现中心(etcd): 1.管理当前注册到服务注册与发现中心的微服务实例元数据信息, 包括服务实例的服务名、IP地址、端口号、服务描述和服务状态等. 2.与注册到服务发现与注册中心的微服务实例维持心跳, 定期检查注册表中的服务实例是否在线, 并剔除无效服务实例信息. 3.提供服务发现能力, 为服务调用方提供服务提供方的服务实例元数据

​CAP理论

​本质上来说, 服务发现就是想要了解集群中是否有进程在监听 udp 或 tcp 端口, 并且通过名字就可以查找和连接.

​解决服务发现的问题:

  1. 一个强一致性、高可用的服务存储目录. 基于Raft算法的etcd天生就是这样一个强一致性高可用的服务存储目录.
  2. 一种注册服务和监控服务健康状态的机制. 用户可以在etcd中注册服务, 并且对注册的服务设置key TTL, 定时保持服务的心跳以达到监控健康状态的效果.
  3. 一种查找和连接服务的机制. 通过在 etcd 指定的主题下注册的服务也能在对应的主题下查找到. 为了确保连接, 我们可以在每个服务机器上都部署一个Proxy模式的etcd, 这样就可以确保能访问etcd集群的服务都能互相连接. lease保持心跳, 实时反应任务执行情况, watch监控.

消息发布、订阅

​构建一个配置共享中心, 数据提供者在这个配置中心发布消息, 而消息使用者则订阅他们关心的主题, 一旦主题有消息发布, 就会实时通知订阅者

​watch 消费者订阅

请添加图片描述

分布式锁

分布式锁应该具备条件:

  • 互斥性: 在任意时刻, 对于同一个锁, 只有一个客户端能持有, 从而保证一个共享资源同一时间只能被一个客户端操作;
  • 安全性: 即不会形成死锁, 当一个客户端在持有锁的期间崩溃而没有主动解锁的情况下, 其持有的锁也能够被正确释放, 并保证后续其它客户端能加锁;
  • 可用性: 当提供锁服务的节点发生宕机等不可恢复性故障时, “热备” 节点能够接替故障的节点继续提供服务, 并保证自身持有的数据与故障节点一致.
  • 对称性: 对于任意一个锁, 其加锁和解锁必须是同一个客户端, 即客户端 A 不能把客户端 B 加的锁给解了.

etcd提供的技术支持

  • Lease 机制

即租约机制(TTL, Time To Live), Etcd 可以为存储的 Key-Value 对设置租约, 当租约到期, Key-Value 将失效删除;同时也支持续约, 通过客户端可以在租约到期之前续约, 以避免 Key-Value 对过期失效. Lease 机制可以保证分布式锁的安全性, 为锁对应的 Key 配置租约, 即使锁的持有者因故障而不能主动释放锁, 锁也会因租约到期而自动释放.

  • Revision 机制

每个 Key 带有一个 Revision 号, 每进行一次事务便加一, 因此它是全局唯一的, 如初始值为 0, 进行一次 put(key, value), Key 的 Revision 变为 1, 同样的操作, 再进行一次, Revision 变为 2;换成 key1 进行put(key1, value)操作, Revision将变为 3;这种机制有一个作用: 通过 Revision 的大小就可以知道写操作的顺序. 在实现分布式锁时, 多个客户端同时抢锁, 根据 Revision 号大小依次获得锁, 可以避免 “羊群效应” (也称"惊群效应"), 实现公平锁.

  • Prefix 机制

即前缀机制, 也称目录机制, 例如, 一个名为 /mylock 的锁, 两个争抢它的客户端进行写操作, 实际写入的Key分别为: key1="/mylock/UUID1",key2="/mylock/UUID2", 其中, UUID表示全局唯一的ID, 确保两个Key的唯一性. 很显然, 写操作都会成功, 但返回的Revision不一样, 那么, 如何判断谁获得了锁呢?通过前缀"/mylock"查询, 返回包含两个Key-Value对应的Key-Value列表, 同时也包含它们的Revision, 通过Revision大小, 客户端可以判断自己是否获得锁, 如果抢锁失败, 则等待锁释放(对应的 Key 被删除或者租约过期), 然后再判断自己是否可以获得锁.

  • Watch 机制

即监听机制, Watch机制支持监听某个固定的Key, 也支持监听一个范围(前缀机制), 当被监听的Key或范围发生变化, 客户端将收到通知;在实现分布式锁时, 如果抢锁失败, 可通过Prefix机制返回的Key-Value列表获得Revision比自己小且相差最小的 Key(称为 Pre-Key), 对Pre-Key进行监听, 因为只有它释放锁, 自己才能获得锁, 如果监听到Pre-Key的DELETE事件, 则说明Pre-Key已经释放, 自己已经持有锁.

实现

​使用IF-Then-Else语句(事务), IF 语言判断etcd服务端是否存在指定的key, 通过该key创建的版本号create_ _revision 是否为0来检查key是否已存在, 如果该key存在, 版本号不为0

​客户端请求在获取到分布式锁后, 如果发生异常, 需要及时将锁释放掉, 因此需要租约, 长时间使用需要续约

请添加图片描述

请添加图片描述

架构及原理

请添加图片描述

​BoltDB是一个单机的支持事务的 kv存储, etcd 的事务是基于boltdb的事务实现的; boltdb 为每一个key都创建一个索引(B+树) ;该B+树存储了key所对应的版本数据(储存key的历史版本信息, 每个key对应一个索引, 索引对对应b+树);

​wal (write ahead log)预写式日志实现事务日志的标准方法;执行写操作前先写日志, 跟mysql中redo类似, wal实现的是顺序写, 而若按照B+树写, 则涉及到多次io以及随机写;

​snapshot快照数据,用于其他节点同步主节点数据从而达到一致性地状态;
类似redis中主从复制史rdb数据恢复;
流程:

  1. leader生成snapshot
  2. leader向follower发送snapshot
  3. follower接收

​gRPC server ectd集群间以及client 与etcd节点间都是通过gRPC进行通讯;

参考资料

  1. Raft动态演示
  2. 官方文档 - etcd官方文档中文版 (gitbook.io)
  3. etcd学习(1)-etcd的使用场景 - ZhanLi - 博客园 (cnblogs.com)
  4. etcd 原理与实践【2022】_哔哩哔哩_bilibili

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

红酒与文学:探索文字背后的酒香

在文学的海洋中,红酒如同一股不同的香风,轻轻拂过书页,为文字的世界增添了一抹诱人的色彩。今天,就让我们一起踏上这段奇妙的旅程,探索红酒与文学之间的奇妙联系,感受文字背后的酒香,特别是以雷…

第11章 规划过程组(二)(11.8排列活动顺序)

第11章 规划过程组(二)11.8排列活动顺序,在第三版教材第388~389页;文字图片音频方式 第一个知识点:主要工具与技术(重要知识点) 1、紧前关系绘图法(PDM)或前导图法&#…

宝塔Linux面板配置环境 + 创建站点

一、安装 (1)进入宝塔官网 https://www.bt.cn/new/index.html (2)点击“ 立即免费安装 ”,选择 Centos安装脚本 (3)进入 ssh 输入以下命令安装宝塔 yum install -y wget && wget -O …

【Docker安装】OpenEuler系统下部署Docker环境

【Docker安装】OpenEuler系统下部署Docker环境 前言一、本次实践介绍1.1 本次实践规划1.2 本次实践简介二、检查本地环境2.1 检查操作系统版本2.2 检查内核版本2.3 检查yum仓库三、卸载Docker四、部署Docker环境4.1 配置yum仓库4.2 检查可用yum仓库4.3 安装Docker4.4 检查Docke…

Golang 依赖注入设计哲学|12.6K 的依赖注入库 wire

一、前言 线上项目往往依赖非常多的具备特定能力的资源,如:DB、MQ、各种中间件,以及随着项目业务的复杂化,单一项目内,业务模块也逐渐增多,如何高效、整洁管理各种资源十分重要。 本文从“术”层面&#…

Linux高并发服务器开发(十一)UDP通信和本地socket通信

文章目录 1 TCP和UDP的区别2 UDPAPI流程服务端流程客户端流程 代码服务端客户端 3 本地socket通信服务端客户端客户端代码 1 TCP和UDP的区别 2 UDP API 流程 服务端流程 客户端流程 代码 服务端 #include<sys/socket.h> #include<stdio.h> #include<arpa/in…

图像增强方法汇总OpenCV+python实现【第一部分:常用图像增强方法】

图像增强方法汇总OpenCVpython实现【第一部分】 前言常用的图像增强方法1. 旋转&#xff08;Rotation&#xff09;&#xff1a;2. 平移&#xff08;Translation&#xff09;&#xff1a;3. 缩放&#xff08;Scaling&#xff09;&#xff1a;4. 剪切变换&#xff08;Shear Trans…

Mac本地部署大模型-单机运行

前些天在一台linux服务器&#xff08;8核&#xff0c;32G内存&#xff0c;无显卡&#xff09;使用ollama运行阿里通义千问Qwen1.5和Qwen2.0低参数版本大模型&#xff0c;Qwen2-1.5B可以运行&#xff0c;但是推理速度有些慢。 一直还没有尝试在macbook上运行测试大模型&#xf…

bug,属性注入时为null

因为在使用拦截器时使用的是new的这个类放容器的 解决方法&#xff1a; 使用有参构造器&#xff0c;在new对象时传入值

SpringBoot 通过Knife4j集成API文档 在线调试

介绍 Knife4j 是一款基于 Swagger 构建的增强型 API 文档生成工具&#xff0c;它提供了更多的定制化功能和界面优化&#xff0c;使得生成的 API 文档更加美观和易用。它可以帮助开发者快速生成和管理 API 文档&#xff0c;支持在线调试和交互。 依赖 <!--knife4j--> &…

使用Python3和Selenium打造百度图片爬虫

开篇 本文的目的在于实现一个用来爬取百度图片的爬虫程序,因该网站不需要登录&#xff0c;所以相对来说较为简单。下面的爬虫程序中我写了比较多的注释&#xff0c;以便于您的理解。 准备 请确保电脑上已经安装了与chrome浏览器版本匹配的chromeDriver&#xff0c;且电脑中已经…

【C++】解决 C++ 语言报错:Dangling Pointer

文章目录 引言 悬挂指针&#xff08;Dangling Pointer&#xff09;是 C 编程中常见且危险的错误之一。当程序试图访问指向已释放内存的指针时&#xff0c;就会发生悬挂指针错误。这种错误不仅会导致程序崩溃&#xff0c;还可能引发不可预测的行为和安全漏洞。本文将深入探讨悬…

C++ | Leetcode C++题解之第214题最短回文串

题目&#xff1a; 题解&#xff1a; class Solution { public:string shortestPalindrome(string s) {int n s.size();vector<int> fail(n, -1);for (int i 1; i < n; i) {int j fail[i - 1];while (j ! -1 && s[j 1] ! s[i]) {j fail[j];}if (s[j 1] …

【Linux】--help,man page , info page

我们知道Linux有很多的命令&#xff0c;那LInux要不要背命令&#xff1f; 答案是背最常用的那些就行了 那有的时候我们想查询一些命令的详细用法该怎么办呢&#xff1f; 这里我给出3种方法 1.--help --help的使用方法很简单啊 要查询的命令 --help 我们看个例子 这里我只…

Object 类中的公共方法详解

Object 类中的公共方法详解 1、clone() 方法2、equals(Object obj) 方法3、hashCode() 方法4、getClass() 方法5、wait() 方法6、notify() 和 notifyAll() 方法 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在 Java 中&#xff0c;Object…

Redis的八种数据类型介绍

Redis 是一个高性能的键值存储&#xff0c;它支持多种丰富的数据类型。每种数据类型都有其特定的用途和底层实现。下面我将介绍 Redis 支持的主要数据类型及其背后的数据结构。 本人这里还有几篇详细的Redis用法文章&#xff0c;可以用来进阶康康&#xff01; 1. 字符串 (Stri…

c++习题08-计算星期几

目录 一&#xff0c;问题 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;问题 二&#xff0c;思路 首先&#xff0c;需要注意到的是3^2000这个数值很大&#xff0c;已经远远超过了long long 数据类型能够表示的范围&#xff0c;如果想要使用指定的数据类型来保存…

Docker实现Redis主从,以及哨兵机制

Docker实现Redis主从,以及哨兵机制 目录 Docker实现Redis主从,以及哨兵机制准备Redis镜像创建Redis主节点配置文件启动Redis从节点确认主从连接哨兵主要功能配置哨兵文件创建Redis哨兵的Docker容器 要通过Docker实现Redis的主从&#xff08;master-slave&#xff09;复制&#…

【WebGIS干货分享】Webgis 面试题-浙江中海达

1、Cesium 中有几种拾取坐标的方式&#xff0c;分别介绍 Cesium 是一个用于创建 3D 地球和地理空间应用的 JavaScript 库。在 Cesium 中&#xff0c;你可以使用不同的方式来拾取坐标&#xff0c;以便与地球或地图上的对象进行交 互。以下是 Cesium 中几种常见的拾取坐标的方式…

重载与覆写介绍

方法重载&#xff08;Overloading&#xff09; 方法重载是指在同一个类中定义多个方法&#xff0c;它们具有相同的名字但参数列表不同。这是通过改变参数的数量、类型的种类或次序来实现的。例如&#xff1a; public class OverloadingExample { // 方法重载可以通过参数的数…