08 | Watch:如何高效获取数据变化通知?
该思维导图由 AI 生成,仅供参考
Watch 特性初体验
- 深入了解
- 翻译
- 解释
- 总结
etcd Watch机制是Kubernetes控制器的核心基础,通过监听、比较资源实际状态与期望状态的一致性来实现数据变化通知。本文深入介绍了etcd Watch机制的设计原理和优化,包括etcd v2和v3中client获取事件的机制、事件存储机制的演变、基于HTTP/2的gRPC协议实现的连接多路复用,以及etcd v3的MVCC机制。文章重点讨论了WatchableKV模块的工作原理,包括最新事件推送、异常场景重试机制和历史事件推送机制。此外,还介绍了etcd如何高效地根据变化的key快速找到监听它的watcher。总的来说,本文对于想要深入了解分布式存储Watch特性的读者具有很高的参考价值。 在获取事件机制、事件历史版本存储两个问题中,作者介绍了etcd v2在使用HTTP/1.x轮询、滑动窗口时,存在大量的连接数、丢事件等问题,导致扩展性、稳定性较差。而etcd v3 Watch特性优化思路是基于HTTP/2的流式传输、多路复用,实现了一个连接支持多个watcher,减少了大量连接数,事件存储也从滑动窗口优化成稳定可靠的MVCC机制,历史版本保存在磁盘中,具备更好的扩展性、稳定性。在实现可靠的事件推送机制问题中,作者通过一个整体架构图带你了解整个Watch机制的核心链路,数据推送流程。 Watch特性的核心实现模块是watchableStore,它通过将watcher划分为synced/unsynced/victim三类,将问题进行了分解,并通过多个后台异步循环 goroutine负责不同场景下的事件推送,提供了各类异常等场景下的Watch事件重试机制,尽力确保变更事件不丢失、按逻辑时钟版本号顺序推送给client。最后一个事件匹配性能问题,etcd基于map和区间树数实现了watcher与事件快速匹配,保障了大规模场景下的Watch机制性能和读写稳定性。 业务场景是希望agent能通过Watch机制监听server端下发给它的任务信息,简要实现如下,你认为它存在哪些问题呢? 它一定能监听到server下发给其的所有任务信息吗?欢迎你给出正确的解决方案。
《etcd 实战课》,新⼈⾸单¥59
全部留言(22)
- 最新
- 精选
- 奕当某个 key 发生变化的一定要去 key 的 watcher 区间树去查询是否对应的 watcher 吗? 这样会不会有很大的浪费,当一个系统 监听了一些不经常变的 key, 另一些经常变化的 key 没有对应的 watcher ,这样经常变化的key就会一直去查询key 的 watcher 区间树。 难道 key 不能直接知道是否有对应的 watcher 呢? (比如 key 的结构体记录一个 watcher Id 的数组)
作者回复: 是的,一定会查,这性能开销很低的。正如我文章中所介绍的,有两类watcher, 一类是监听一个key的watcher,这种直接使用map来保存,也就是检查这个key是否有相关watcher,时间复杂度是o(1),另一类是监听整个区间的watcher,查找这个key落在了哪些watcher监听的范围,一般情况下,时间复杂度o(log n), n是你创建的watcher数。而你建议的方案,使用key结构体记录一个watcher id数组,这在key非常多的情况下,内存开销是非常大,假设一个watcher监听了一个非常大的key范围,那么etcd创建此watcher的时候,还需要遍历这个key范围,给key增加相应的watcher id, 不仅内存,cpu开销也是不可忽略的。 在哪些场景下watcher事件通知性能会非常慢呢?如果你成千上万个watcher,监听同一个key或者范围时,就会导致性能极差。
2021-02-06217 - 七里如何保证WatchableKV 模块启动的syncVictimsLoop是可靠的呢?机器重启了怎么办?
作者回复: 好问题,整个watch链路的可靠性,不能光靠server,从业务逻辑正确使用watch api到client watch中断重试机制,再到本讲介绍的server推送机制,层层相连才能尽量保证watch事件可靠性。如果机器重启了,这时就依赖client库的重试机制了,client收到每个watch事件时,会记录收到的版本号,连接到新节点后,再次创建watcher时会带上这个版本号,然后就会进入历史数据同步逻辑。
2021-02-0714 - 写点啥呢请问下老师,如果etcd集群某个节点崩溃或者网络问题导致client/server间连接断开,etcd是如何处理watch重新连接?如果是在另外一个节点重连后,etcd如何确定哪些event已经发送来避免event重复发送呢? 谢谢老师
作者回复: etcd clientv3 watch库有中断重连、恢复机制,它会记录上次已收到的watch事件版本号,重启到新节点后,创建watcher的时候会带上这个版本,这样就可以尽量避免event重复发送哈,你可以使用etcd 3.4.9版本自己测试体验下。
2021-02-058 - 奕带 --rev 版本号的监听,不是从需要监听某个 key 的某个指定的版本开始吗? 文章中怎么写的是集群的版本号
作者回复: 版本号是集群的逻辑时间,参考07,监听key时,你可以指定任意一个时间点,过去、未来的版本号都可以。
2021-02-051 - 八台上想问一下 每个key 有没有时间戳呢 想看真实的创建时间
作者回复: 目前没有,你可以通过版本号信息来判断对比key的创建、修改时间等,它是个逻辑时间
2021-08-03 - BeanNan想问下老师,思考题的答案在哪有解惑?2022-01-043
- 谢小路学 etcd 还是需要些功底的,基础薄弱应该看不懂这些。2021-04-0713
- Geek_7d539e有一个地方没有写明: watch 通过 raft 通讯模块,传播到各个节点,也就是给个节点都有这个 watch(id) ,key 的 put 更新操作,给个节点自然都能监听到该 key 的变化,那么是各个节点都会去通知这个变化吗?还是就只有一个节点会去通知 client ?我本人猜测是,每个节点都会去通知,但是并不是每个节点都有 client watch steam ,没有连接 stream 就自然丢弃通知,有 stream 才会去落实通知。请老师释疑下,多谢。还有顺道多问一个问题,put 请求是单 key 的事务操作吗?2021-07-2741
- Geek_539c73越底层,越是数据结构2023-07-26归属地:北京
- 踏雪无痕“同时当 watch 连接的节点故障,clientv3 库支持自动重连到健康节点,并使用之前已接收的最大版本号创建新的 watcher,避免旧事件回放等。” 作者你好,请问这一段话有没有对应的官网文档相关内容,我找了下没找到。2023-06-27归属地:浙江