本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢。

1、etcd读请求概览

etcd是典型的读多写少存储,在我们实际业务场景中,读一般占据2/3以上的请求。一个读 请求从client通过Round-robin(轮询)负载均衡算法,选择一个etcd server节点,发出 gRPC请 求,经过etcd server的 KVServer模块、线性读模块、MVCC的treelndex和 boltdb模块紧 密协作,完成了一个读请求。

思考:通过etcdctl执行如下命令etcd是如何工作的?

etcdctl get hello ‐‐endpoints 192.168.65.210:2379,192.168.65.211:2379,19 2.168.65.212:2379

2、详细步骤解读

2.1 Client 层

主要是对应到步骤 1

1、首先,etcdctl 会对命令中的参数进行解析。

  • get 是请求的方法,它是 KVServer 模块的 提供的API;
  • hello是 我们查询的 key 名;
  • endpoints 是我们后端的 etcd 地址。通常,生产环境下中需要配置多个endpoints,这样在 etcd 节点出现故障后,client 就可以自动重连到其它正常的节点,从而保证请求的正常执行。

2、在解析完请求中的参数后,etcdctl 会创建一个 clientv3 库对象,使用 KVServer 模块 的 API 来访问 etcd server。

etcd clientv3 库采用的负载均衡算法为 Round-robin。针对每一个请求,Round-robin 算法通过轮询的方式依次从 endpoint 列表中选择一个 endpoint 访问 (长连接),使 etcd server 负载尽量均衡。

2.2 KVServer 与 拦截器

主要是对应到步骤 2

client 发送 Range RPC 请求到了 server 后就进入了 KVServer 模块。

etcd 通过拦截器以非侵入式的方式实现了许多特性,例如:丰富的 metrics、日志、请求行为检查、所有请求的执行耗时及错误码、来源IP 等。拦截器提供了在执行一个请求前后 的 hook 能力,除了 debug 日志、metrics 统计、对 etcd Learner 节点请求接口和参数限制等能力,etcd 还基于它实现了以下特性:

  • 要求执行一个操作前集群必须有 Leader;

  • 请求延时超过指定阈值的,打印包含来源 IP 的慢查询日志 (3.5 版本)。

server 收到 client 的 Range RPC 请求后,根据 ServiceName 和 RPC Method 将请求转 发到对应的 handler 实现,handler 首先会将上面描述的一系列拦截器串联成一个拦截器再执行,在拦截器逻辑中,通过调用 KVServer 模块的 Range 接口获取数据。

2.3 串行读与线性读

流程三和四.

etcd 为了保证服务高可用,生产环境一般部署多个节点,多节点之间的数据由于延迟等关系可能会存在不一致的情况。

当 client 发起一个写请求后分为以下几个步骤:

1、Leader 收到写请求,它会将此请求持久化到 WAL 日志,并广播给各个节点;

只有 Leader 节点能处理写请求。

2、若一半以上节点持久化成功,则该请求对应的日志条目被标识为已提交;

3、etcdserver 模块异步从 Raft 模块获取已提交的日志条目,应用到状态机 (boltdb 等)。

此时若client 发起一个读取 hello 的请求,假设此请求直接从状态机中读取,如果连接到的是C节点,若C节点磁盘I/O出现波动,可能导致它应用已提交的日志条目很慢,则会出现更新 hello 为 world 的写命令,在client读 hello 的时候还未被提交到状态机,因此就可能读取到旧数据,如上图查询hello流程所示。

所以在多节点etcd集群中,各个节点的状态机数据一致性存在差异。而我们不同业务场景 的读请求对数据是否最新的容忍度是不一样的,有的场景它可以容忍数据落后几秒甚至几分 钟,有的场景要求必须读到反映集群共识的最新数据。根据业务场景对数据一致性差异的接受程度。

**etcd 中有两种读模式: **

1、串行 (Serializable) 读:

直接读状态机数据返回、无需通过 Raft 协议与集群进行交互, 它具有低延时、高吞吐量的特点,适合对数据一致性要求不高的场景。

2、线性读:

etcd 默认读模式是线性读,需要经过 Raft 协议模块,反应的是集群共识,因 此在延时和吞吐量上相比串行读略差一点,适用于对数据一致性要求高的场景。

对数据敏感度较低的场景:

  • 直接读状态机数据返回、无需通过 Raft 协议与集群进行交互的模式,在 etcd 里叫做串行 (Serializable) 读,它具有低延时、高吞吐量的特点,适合对数据一致性要求不高的场景。

对数据敏感性高的场景:

  • 在 etcd 里面,提供了一种线性读模式来解决对数据一致性要求高的场景。

什么是线性读呢?

你可以理解一旦一个值更新成功,随后任何通过线性读的 client 都能及时访问到。虽然集群中有多个节点,但 client 通过线性读就如访问一个节点一样。etcd 默认读模式是线性读,因为它需要经过 Raft 协议模块,反应的是集群共识,因此在延时和吞吐量上相比串行读略差一点,适用于对数据一致性要求高的场景。

2.4 ReadIndex

在 etcd 3.1 引入了 ReadIndex 机制,保证在串行读的时候,也能读到最新的数据。

接下来看看线性读的执行流程

具体流程如下:

  • 当收到一个线性读请求时,它首先会从Leader获取集群最新的已提交的日志索引(committed index),如上图中的流程二所示。

  • Leader收到ReadIndex请求时,为防止脑裂等异常场景,会向Follower节点发送心跳确认,一半以上节点确认Leader身份后才能将已提交的索引(committed index)返回给节点C(上图中的流程三)。

  • 节点则会等待,直到状态机已应用索引 (applied index)大于等于Leader的已提交索引时(committed Index)(上图中的流程四),然后去通知读请求,数据已赶上 Leader,你可以去状态机中访问数据了(上图中的流程五)。

以上就是线性读通过ReadIndex机制保证数据一致性原理,当然还有其它机制也能实现线性读,如在早期etcd 3.0中读请求通过走一遍Raft 协议保证一致性,这种Raft log read机制 依赖磁盘IO,性能相比 ReadIndex较差。

总体而言,KVServer模块收到线性读请求后,通过架构图中流程三向Raft模块发起 ReadIndex请求,Raft模块将Leader最新的已提交日志索引封装在流程四的ReadState结构体,通过channel层层返回给线性读模块,线性读模块等待本节点状态机追赶上Leader进度,追赶完成后,就通知KVServer模块,进行架构图中流程五,与状态机中的 MVCC模块进行进行交互了。

2.5 MVCC

流程五中的多版本并发控制(Multiversion concurrency control)模块为了解决etcd v2不支持保存key的历史版本、不支持多key事务等问题而产生的。它核心由内存树形索引模块 (treelndex)和嵌入式的KV持久化存储库 boltdb 组成。boltdb是个基于B+ tree实现的 key-value键值库,支持事务,提供Get/Put等简易API给etcd操作。

etcd MVCC 具体方案如下:

  • 每次修改操作,生成一个新的版本号 (revision),以版本号为 key, value 为用户 key-value 等信息组成的结构体存储到 blotdb。
  • 读取时·先从 treeIndex 中获取 key 的版本号·,再以版本号作为 boltdb 的 key,从 boltdb 中获取其 value 信息。

2.6 treelndex

treelndex模块是基于Google开源的内存版btree 库实现的,treeIndex模块只会保存用户的key和相关版本号信息,用户 key 的value数据存储在boltdb里面,相比ZooKeeper和 etcd v2全内存存储,etcd v3对内存要求更低。

简单介绍了etcd如何保存 key的历史版本后,架构图中流程六也就非常容易理解了,它需要从treelndex模块中获取 hello这个 key对应的版本号信息。treeIndex模块基于 B-tree快速查找此 key,返回此 key对应的索引项keyIndex即可。索引项中包含版本号等信息。

2.7 buffer

在获取到版本号信息后,就可从boltdb模块中获取用户的key-value数据了。不过并不是所有请求都—定要从 boltdb 获取数据。etcd出于数据一致性、性能等考虑,在访问boltdb前,首先会从一个内存读事务 buffer中,二分查找你要访问key是否在 buffer里面,若命中则直接返回。

2.8 boltdb

若buffer未命中,此时就真正需要向boltdb模块查询数据了,进入了流程七。 我们知道MySQL通过 table 实现不同数据逻辑隔离,那么在boltdb是如何隔离集群元数据 与用户数据的呢?答案是bucket

boltdb 里每个 bucket 类似对应 MySQL 一个表,用户的 key 数据存放的 bucket 名字的是 key,etcd MVCC 元数据存放的 bucket 是 meta。

我猜测这里的意思是每个key都当做一个 bucket,然后bucket的名字是 key。这里是猜测的,待验证,若有知道的朋友,请不吝赐教,十分感谢。

因boltdb使用B+ tree来组织用户的key-value数据,获取 bucket key对象后,通过boltdb 的游标Cursor可快速在B+ tree找到 key hello对应的value数据,返回给client。 到这里,一个读请求之路执行完成。

文章来源:

etcd读请求执行流程-视频教程


etcd教程(七)---读请求执行流程分析

05、etcd 读请求执行流程的更多相关文章

  1. Spring MVC请求执行流程

    学习Spring MVC时间有点长了,但是最近打算找工作,需要重新了解下,所以又去温故知新了.Spring MVC就是用来写web的框架,简化你写web的一些不必要的流程,让程序员能专注于业务逻辑也就 ...

  2. springmvc对请求执行流程

    doService-->getHandlerMapping-->handlerMapping-->getHandler-->HandlerExecutionChain--> ...

  3. 一文读懂Spring MVC执行流程

    说到Spring MVC执行流程,网上有很多这方面的文章介绍,但是都不太详细,作为一个初学者去读会有许多不理解的地方,今天这篇文章记录一下我学习Spring MVC的心得体会 话不多说,先上图:   ...

  4. Java——一文读懂Spring MVC执行流程

    说到Spring MVC执行流程,网上有很多这方面的文章介绍,但是都不太详细,作为一个初学者去读会有许多不理解的地方,今天这篇文章记录一下我学习Spring MVC的心得体会 话不多说,先上图: Sp ...

  5. 040 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 02 while循环的执行流程

    040 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 02 while循环的执行流程 本文知识点:while循环的执行流程 三种循环结构中的第一种--wh ...

  6. am335x uboot2016.05 (MLO u-boot.img)执行流程

    am335x的cpu上电后,执行流程:ROM->MLO(SPL)->u-boot.img 第一级bootloader:引导加载程序,板子上电后会自动执行这些代码,如启动方式(SDcard. ...

  7. am335x uboot2016.05 (MLO u-boot.img)执行流程(转)

    am335x的cpu上电后,执行流程:ROM->MLO(SPL)->u-boot.img 第一级bootloader:引导加载程序,板子上电后会自动执行这些代码,如启动方式(SDcard. ...

  8. 追源索骥:透过源码看懂Flink核心框架的执行流程

    li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt, ...

  9. Spring Security 案例实现和执行流程剖析

    Spring Security Spring Security 是 Spring 社区的一个顶级项目,也是 Spring Boot 官方推荐使用的安全框架.除了常规的认证(Authentication ...

  10. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证

    Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...

随机推荐

  1. 使用shell进行简单分析增量更新时间的方法

    使用shell进行简单分析增量更新时间的方法 思路 产品里面更新增量时耗时较久, 想着能够简单分析下哪些补丁更新时间久 哪些相同前缀的补丁更新的时间累积较久. 本来想通过全shell的方式进行处理 但 ...

  2. js赋值的两种方式

    第一种 let obj=[ { value:undefined } ] obj[0].value.value='zahngsan' obj[0].value.label='张三' 机智的小伙伴,可能已 ...

  3. vm-storage在全部都是新metric情况下的写入性能测试

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 vm-storage中,写入索引的性能要比写入data p ...

  4. CCFLOW源码解读系列01-----发起流程

    1.发起流程 发起流程时主要做了两件事:一是写入业务数据表,二是新建一条审批流程记录. 发起流程的方法 public static Int64 Node_CreateStartNodeWork(str ...

  5. 每日一库:cobra 简介

    当你需要为你的 Go 项目创建一个强大的命令行工具时,你可能会遇到许多挑战,比如如何定义命令.标志和参数,如何生成详细的帮助文档,如何支持子命令等等.为了解决这些问题,github.com/spf13 ...

  6. Fabric-ca server端与client端交互

    本文介绍Fabric-ca server端和client端的交互过程. 在server端执行Start()命令时,会调用registerHandlers()函数,其作用就是注册处理客户端请求的程序: ...

  7. TienChin-课程管理-课程更新接口

    更改包名 将之前的 entity 更改为 domain: 将之前的 validator 包当中的校验分组接口移动到 common 模块当中,因为其它模块也需要使用就放到公共当中进行存储. 更改完毕之后 ...

  8. 设置两个Chrome浏览器 一个正常使用 一个无图片版

    添加两个Chrome浏览器 双击打开Chrome浏览器,点击右上角头像,点击添加 选择"在不登录帐号的情况下继续",创建一个名字,选个配色,勾选下面的创建桌面快捷方式 此时会打开一 ...

  9. 苹果M3 Max有两种版本:14+40?还是16+40?

    最近有关苹果M3系列处理器的消息突然多了起来,包括M3.M3 Pro.M3 Max,都将升级为台积电3nm工艺,但规格上比较保守,至少核心数量不会大幅增加. 此前说法称,M3 Max将配备14个CPU ...

  10. 使用KVM创建OEL虚拟机

    在Linux工作站上使用KVM创建虚拟机. 首先说下我的需求: 1.其他LAN内的笔记本也可以连接到这些KVM的虚拟机,因此需要配置使用桥接网络 2.创建一个虚拟机,采用最小化安装系统,作为基础模版, ...