etcd 实现与选型分析(二)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: etcd 实现与选型分析(二)

变更通知

概念

etcd 通过对 watcher 进行分类,来实现事件的可靠性:

  • synced watcher,此类 watcher 监听的数据都已经同步完毕,在等待新的变更。
  • unsynced watcher,此类 watcher 监听的数据还未同步完成,落后于当前最新数据变更,正在努力追赶。
  • victim watcher,此类 slower watcher 的推送 channel buffer 堆满,etcd 会将其移动到专门的队列中异步机制重试。

订阅流程

  • 当 Client 发起一个 watch key 请求的时候,etcd 的 WatchServer 收到 watch 请求后,会创建一个 serverWatchStream, 它负责接收 client 的 gRPC Stream 的 create/cancel watcher 请求 (recvLoop goroutine),并将从 MVCC 模块接收的 Watch 事件转发给 client(sendLoop goroutine)。
  • 当 serverWatchStream 收到 create watcher 请求后,serverWatchStream 会调用 MVCC 模块的 WatchStream 子模块分配一个 watcher id,并将 watcher 注册到 MVCC 的 WatchableKV 模块。
  • etcd 启动后,WatchableKV 模块会运行 syncWatchersLoop 和 syncVictimsLoop goroutine,分别负责不同场景下的事件推送。

etcd 使用 map 记录了监听单个 key 的 watcher,但是你要注意的是 Watch 特性不仅仅可以监听单 key,它还可以指定监听 key 范围、key 前缀,因此 etcd 还使用了区间树。当收到创建 watcher 请求的时候,它会把 watcher 监听的 key 范围插入到上面的区间树中,区间的值保存了监听同样 key 范围的 watcher 集合 /watcherSet。

当产生一个事件时,etcd 首先需要从 map 查找是否有 watcher 监听了单 key,其次它还需要从区间树找出与此 key 相交的所有区间,然后从区间的值获取监听的 watcher 集合。区间树支持快速查找一个 key 是否在某个区间内,时间复杂度 O(LogN),因此 etcd 基于 map 和区间树实现了 watcher 与事件快速匹配,具备良好的扩展性。

推送流程

  • 当你创建完成 watcher 后,此时你执行 put hello 修改操作时,如上图所示,请求经过后的 mvccpb.KeyValue 保存到一个 changes 数组中。
  • 在 put 事务结束时,它会将 KeyValue 转换成 Event 事件,然后回调 watchableStore.notify 函数。notify 会匹配出监听过此 key 并处于 synced watcherGroup 中的 watcher,同时事件中的版本号要大于等于 watcher 监听的最小版本号,才能将事件发送到此 watcher 的事件 channel 中。

注意

若 watcher 监听的版本号已经小于当前 etcd server 压缩的版本号,历史变更数据就可能

已丢失,因此 etcd server 会返回 ErrCompacted 错误给 client。client 收到此错误后,需重新获取数据最新版本号后,再次 Watch。在业务开发过程中,使用 Watch API 最常见的一个错误之一就是未处理此错误。

其次,Watch 返回的  WatchChan  有可能在运行过程中失败而关闭,此时  WatchResponse.Canceled  会被置为  trueWatchResponse.Err()  也会返回具体的错误信息。所以在 range WatchChan 的时候,每一次循环都要检查  WatchResponse.Canceled,在关闭的时候重新发起 Watch 或报错。

选型分析

方案选型可以从业务系统的需求和 etcd 的特性、性能,两个方面着手。

业务系统

先看使用 etcd 提供服务的目标系统。如果你正在深入 Kubernetes 或开始使用服务网格,您可能会遇到术语“控制平面(control plane)”和“数据平面(data plane)”。术语 “控制平面” 和 “数据平面” 都是关于关注点的分离,即系统内职责的明确分离。控制平面是一切与策略建立和下发有关的部分,而数据平面是一切与执行策略有关的部分。当控制平面出现故障,只会影响新的策略变更变更,但不会影响已有策略执行,即,数据平面的功能。

以 Kubernetes 为例,其核心服务包括:

组件 描述
kube-apiserver 提供了资源的唯一入口,并提供认证、授权、访问控制、API 注册和发现等
kube-scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
kube-controller-manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
etcd 存储整个集群的状态
kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡

以上服务故障,并不会影响当前已有 Pod 正常对外提供服务。

Why etcd

再看 etcd 本身。要了解 etcd 适用的场景,质量最高的来源是其官网。

介绍:

“etcd” 名字来源于两个想法:unix “/etc” 文件夹和 分布式( “d”istributed)系统。“/etc” 文件夹是存储单个系统的配置数据的地方,而 etcd 存储大规模分布式系统的配置信息。因此,“d”istributed “/etc” 是 “etcd”。

etcd 被设计为大规模分布式系统的通用基座。这类系统永远不容忍裂脑操作,并愿意牺牲可用性来实现该目标。

分布式系统使用 etcd 用于配置管理、服务发现和协调分布式工作。etcd 的常见分布式模式包括领导者选举、分布式锁和监控机器活动。

使用场景:

  • CoreOS 的 Container Linux:在 Container Linux 上运行的应用程序可以获得自动、零停机的 Linux 内核更新。Container Linux 使用 Locksmith 来协调更新。Locksmith 在 etcd 上实现了分布式信号量,以确保在任何给定时间只有集群的一个子集在重新启动。
  • Kubernetes 将配置数据存储到 etcd 中,用于服务发现和集群管理;etcd 的一致性对于正确调度和操作服务至关重要。Kubernetes API 服务器将集群状态持久化为 etcd。它使用 etcd 的 watch API 来监视集群并生效关键的配置变更。( 2016 年 Kubernetes 1.6 发布,默认启用 etcd v3,助力 Kubernetes 支撑 5000 节点集群规模)

其他:

  • 最大可靠数据库大小: 数 GB
  • 因为缺少数据分片,复制无法水平扩展
  • 租约提供了一种用于减少中止请求数量的优化机制。

——— 来源:etcd versus other key-value stores | etcd

从基本介绍以及使用场景来看,etcd 的定位在于存储数据量小、更新频率低的数据,用于一致性要求高于可用性、无需水平扩展的场景。

性能

硬件推荐

超大型集群 为例,一个超大型型集群服务的客户端超过 1500 个,每秒请求超过 10000 个,存储数据超过 1 GB。

云厂商 机型 CPU 内存 (GB) 最大并发 IOPS 磁盘带宽 (MB/s)
AWS m4.4xlarge 16 64 16,000 250
GCE n1-standard-16 + 500GB PD SSD 16 60 15,000 250
性能指标

压测的硬件配置:

  • Google Cloud Compute Engine
  • 3 machines of 8 vCPUs + 16GB Memory + 50GB SSD
  • 1 machine(client) of 16 vCPUs + 30GB Memory + 50GB SSD
  • Ubuntu 17.04
  • etcd 3.2.0, go 1.8.3

写性能

Key 数量 Key 大小 (byte) Value 大小 (byte) 连接数 Client 数 目标 etcd server 平均写 QPS 平均请求延迟 平均服务 RSS
10,000 8 256 1 1 leader only 583 1.6ms 48 MB
100,000 8 256 100 1000 leader only 44,341 22ms 124MB
100,000 8 256 100 1000 all members 50,104 20ms 126MB

读性能

请求数 Key 大小 (byte) Value 大小 (byte) 连接数 Client 数 一致性 平均读 QPS 平均请求延迟
10,000 8 256 1 1 Linearizable 1,353 0.7ms
10,000 8 256 1 1 Serializable 2,909 0.3ms
100,000 8 256 100 1000 Linearizable 141,578 5.5ms
100,000 8 256 100 1000 Serializable 185,758 2.2ms
总结

一般 etcd 的集群为 3 或 5 个节点,Key 数量为 10w~ 规模下,预估集群性能如下:

  1. 写请求只有 Leader 才能处理,所以写性能不随节点数增加而增加,只取决于单机配置,处理量级大概为 1w~ QPS,平均延迟在 10ms~50ms。
  2. 串行读取所有节点均可处理,无需共识,处理量级大概为 10w~ QPS,平均延迟在 5ms 以内。
  3. 线性读取所有节点均可处理,但需要请求 Leader 获取 ReadIndex,性能会稍差,节点数对其提升有限,且容易受写请求影响,处理量级大概为 10w QPS,平均延迟在 10ms 以内。

适用场景

综合目标系统和 etcd 本身的细节来看:

  1. 首先,不建议将 etcd 用于目标系统的数据面。例如,配置中心产品,不适合使用 etcd 作为存储;
  2. 其次,谨慎将 etcd 用于对数据分片和水平扩展有要求的控制面系统。例如:跨可用区的服务发现,可以对服务类型进行区分,尽量减少多个可用区之间需要复制同步的服务数据量。
  3. 最后,etcd 租约、变更通知等功能的复杂度偏高。技术可控要求较高的系统,应谨慎使用相关功能。

本文作者 : cyningsun

本文地址https://www.cyningsun.com/01-27-2023/etcd-implement-and-tech-selection.html

版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!

# 数据库

  1. 深入理解 Redis cluster GOSSIP 协议
  2. 如何配置 go-redis 连接池
  3. 如何使用 Redis 存储对象
  4. Redis cluster 细节与技术选型
  5. MySQL 设计与查询规范
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
存储 Kubernetes 算法
ASI 2021 年双十一万级别超大规模集群的高性能提升
ASI 作为云原生的引领实施者,它的高性能,高可用,它的稳定性影响着甚至决定着阿里集团和云产品的业务的发展。
2881 101
ASI 2021 年双十一万级别超大规模集群的高性能提升
|
8月前
|
人工智能 安全 API
最近谈论 SSE 和 WebSocket 的人越来越多的原因
实时通信已经成了大模型应用的标配。
1159 247
最近谈论 SSE 和 WebSocket 的人越来越多的原因
|
10月前
|
存储 缓存 固态存储
优化Elasticsearch 硬件配置
优化Elasticsearch 硬件配置
446 5
|
11月前
|
机器学习/深度学习 测试技术
强化学习让大模型自动纠错,数学、编程性能暴涨,DeepMind新作
【10月更文挑战第18天】Google DeepMind提出了一种基于强化学习的自动纠错方法SCoRe,通过自我修正提高大型语言模型(LLMs)的纠错能力。SCoRe在数学和编程任务中表现出色,分别在MATH和HumanEval基准测试中提升了15.6%和9.1%的自动纠错性能。
261 4
|
关系型数据库 数据库 PostgreSQL
PostgreSQL 11 新特性解读 : Initdb/Pg_resetwal支持修改WAL文件大小
PostgreSQL 11 版本的一个重要调整是支持 initdb 和 pg_resetwal 修改 WAL 文件大小,而 11 版本之前只能在编译安装 PostgreSQL 时设置 WAL 文件大小。
9185 1
|
存储 Kubernetes 安全
在K8S中,etcdctl如何使用?
在K8S中,etcdctl如何使用?
|
Go
Golang的time.NewTimer单次定时器使用案例
这篇文章介绍了Go语言中time包的多种定时器使用案例,包括单次定时器的创建、阻塞程序运行的Sleep函数、重置和停止定时器的方法,以及After和AfterFunc函数的使用。
201 5
Golang的time.NewTimer单次定时器使用案例
|
11月前
|
缓存 监控 JavaScript
Node.js中基于node-schedule实现定时任务之详解
Node.js中基于node-schedule实现定时任务之详解
534 0
|
存储 缓存 Java
int 和 Integer 哪一个占用更多内存?
【8月更文挑战第21天】
394 0
|
安全 网络协议 Java
技术好文:SpringBoot学习(五)RSocket和Security
技术好文:SpringBoot学习(五)RSocket和Security