• hiroshi
    2021-02-16
    老师,readIndex 需要请求 leader,那为啥不直接让 leader 返回读请求的结果,而要等待自己的进度赶上 leader?

    作者回复: 非常好的问题,我个人认为主要还是性能因素,我记得etcd v2早期的时候如果你指定线性读/共识读,它就是直接转发给leader的。后来在etcd v3.0中实现了raft log read但是要走一遍raft log,读涉及到磁盘IO,v3.1中引入了readIndex机制,它是非常轻量级的,开销较小,相比各个follower都转发给leader会导致leader负载较高,特别是expensive request场景,性能会急剧下降,leader的内存、cpu、网络带宽资源都很容易耗尽,readIndex机制的引入,使得每个follower节点都可以处理读请求,极大扩展提升了写性能。

    共 7 条评论
    66
  • 姜姜
    2021-01-26
    老师,文中有些地方不太明白: 1, KVServer中的拦截器 我认为它只是作为一个辅助的功能吧,用于实现一些观测功能。但对于一个普通的读请求,是否必须通过拦截器才能完成读取数据的操作? 2, 文中“handler 首先会将上面描述的一系列拦截器串联成一个执行” 这段话中,拦截器是一系列的,一系列是指会有多个拦截器吗?难道不是一个请求只注册一个拦截器吗,还能注册多个?为什么要注册多个? “串联成一个执行”,如何串联成一个?将多个拦截器串联成一个拦截器? 3, 串行读与线性读 这里我理解串行读是“非强一致性读”,线性读是“强一致性读”,对吗? 而且这里的“串行”总让我想到“并行/串行”的概念,不知有关系吗? 4, ReadIndex,committed index,applied index 这几种索引底层实现是一样的吗,它们的数据结构是怎样的?是对同一份数据,分别建立不同的索引?又为什么建立这么多种索引? 5,版本号 您说是一个递增的全局ID, revision{2, 0},ID指的是2还是0? 版本号的格式是怎样的,另一个数字代表什么? 6, bucket 请问一个 bucket 相当于一整个 B+ tree 索引树吗?还是相当于 B+ tree 中一个节点?
    展开

    作者回复: 谢谢你的提问,我先简单快速回答下,后面不清楚的再写答疑文章深入解答 问题1和2是gRPC拦截器相关知识我推荐你看下这篇文章https://zhuanlan.zhihu.com/p/80023990 问题3你理解串行读是“非强一致性读”,线性读是“强一致性读”没问题,至于串行含义并非你想的那样,你可以参考下维基百科的定义, 09事务篇我也会介绍事务隔离中的串行化 https://en.wikipedia.org/wiki/Serializability 问题4 建议先去阅读下04 raft篇,它本值上就是一个uint64的索引,表示日志条目序号 问题5,{2,0}={major,sub} 2是etcd mvcc事务版本号全局递增,0是事务内子版本号随修改操作递增(比如一个txn事务中多个put/delete操作,其会从0递增),07 mvcc会详细介绍 问题6,一个bucket对应一个颗B+tree

    共 6 条评论
    29
  • 小军
    2021-01-26
    请问老师,当Readindex结束并等待本节点的状态机apply的时候,key又被最新的更新请求给更新了怎么办,这个时候读取到的value是不是又是旧值了

    作者回复: 线性读,读出来的值实际上是你发出读请求时间点的集群最新共识数据,在你读请求发出后,若耗时一定时间还未完成,在这过程中leader又收到了写请求更新了它, 的确你原来读出来的值相比最新的集群共识就是旧的,在实际应用中,我们一般会通过增加版本号检测识别此类问题,后面事务篇会详细和你介绍

    
    22
  • chapin
    2021-01-26
    没有基础,学习这个,可能会比较吃力。

    作者回复: 没关系的,可以先大概看一篇,了解整个流程,不懂什么地方可以等学完后面后,回过头来再看就非常亲切了,后面每节中都有etcd特性体验案例,建议你跟着我一起实际操作下,比如02你就先准备好环境,能用goreman快速启一个多节点集群,也可以自己直接二进制启动一个单节点集群,然后体验一下get,put命令,随着后面的学习你会越来越了解etcd

    
    10
  • 站在树上的松鼠
    2021-01-22
    老师,下面这句话没有理解到,麻烦解答下呢,谢谢! 在client 3.4之前的版本中,负载均衡算法有一个严重的Bug:如果第一个节点异常了,可能会导致你的client访问etcd server异常。 (1)这里第一个节点怎么理解呢? 是指的负载均衡刚好选中的那个etcd server节点异常吗? (2)如果访问的节点异常了,是client库中会做重试机制,还是业务代码需要做重试呢?

    作者回复: 感谢超凡帮忙解答第一点,第二点取决于rpc方法,range clientv3库有重试策略,参考一下这个文件clientv3/retry.go

    共 4 条评论
    7
  • jeffery
    2021-01-22
    干货太多需要慢慢消化!老师能把课程代码放到github上吗……谢谢老师

    作者回复: 嗯,不清楚的地方不要急,后面的每节会帮助你一个个解开疑问

    
    7
  • Want less
    2021-01-27
    当收到一个线性读请求时,它首先会从 Leader 获取集群最新的已提交的日志索引 (committed index)。 所有的client请求不是应该都通过leader下发至follower吗?

    作者回复: 不是的哈,follower节点也可以处理读请求的,只是线性读时需要向leader发送readindex消息,然后确保本节点数据是最新的

    共 2 条评论
    5
  • Alery
    2021-01-26
    请教一个问题,在treeIndex中查询key对应的版本号,这里是会返回当前key的所有版本号吗?

    作者回复: 嗯,每个key在treeIndex中有一个对应的数据结构keyIndex,它保存了所有版本号(若未压缩),07讲mvcc将详细介绍

    
    5
  • yayiyaya
    2021-02-04
    问答: etcd 在执行读请求过程中涉及磁盘 IO 吗? 答: 涉及到磁盘, 当读请求从treeIndex获取到用户的 key 和相关版本号信息后,去查询value值时, 没有命中 buffer, 会从boltdb获取数据, 这个时候就涉及到了磁盘。

    作者回复: etcd启动的时候通过mmap将db文件映射到内存,会告诉内核预读文件,下一讲给了参考答案

    
    4
  • 于途
    2021-01-22
    如果你的 client 版本 <= 3.3,那么当你配置多个 endpoint 时,负载均衡算法仅会从中选择一个 IP 并创建一个连接(Pinned endpoint) 请问,此句提到的负载均衡算法是否等同:随机选中某个IP?

    作者回复: 嗯,可以理解为随机,首先它会尝试连接所有etcd节点,连接建立后选择一个固定的长连接,其他关闭

    
    4