在学习etcd之前,我们先来聊一聊etcd这个名字的由来。etcd中的etc取自“unix”系统的“/etc”目录,‘d’指的是分布式系统(distributed system)。在unix系统中"/etc"目录用于存储系统的配置数据,从名字看etcd可用于存储大型可扩展分布式系统的配置数据,也可以把etcd简单的理解为分布式“/etc”目录。
etcd被设计为大型分布式系统的通用基座,这些系统永远不会容忍裂脑操作,并且愿意牺牲可用性来实现此目的。etcd以一致且容错的方式存储元数据。etcd集群旨在提供稳定,可靠,可伸缩和性能优异的的键值存储能力。
分布式系统将etcd用作配置管理,服务发现和协调分布式工作的一致键值存储。很多组织已经使用etcd构建了生产系统,比如容器调度,服务发现和分布式数据存储。使用etcd的常见分布式模式包括领导者选举,分布式锁和监视机器活动状态。
使用场景
-
CoreOS的Linux容器:在Container Linux上运行的应用程序会自动获得零停机Linux内核更新。 Container Linux使用锁提供协调更新的能力。 locksmith在etcd上实现了分布式信号量,以确保在任何给定时间内仅集群的一小部分正在重启。
-
Kubernetes使用etcd存储配置数据以实现服务发现和集群管理;etcd的一致性是正确调度和操作服务的关键。Kubernetes的API Server把集群的状态存储在etcd中,使用etcd的Watch API监控集群和回滚关键配置变化。
比较表格
也许etcd看起来已经非常合适,但是和所有的技术决策一样仍然需要循序渐进。下面从技术和功能角度对比etcd和其他几个替代方案之间的差异,但是仍然推荐使用etcd。
etcd | ZooKeeper | Consul | NewSQL | |
---|---|---|---|---|
并发原语 | Lock RPCs,,Election RPCs ,command line locks,command line elections, recipes in go | Java开发的curator | 原生锁API | 很少 |
线性读 | Yes | No | Yes | Sometimes |
多版本并发控制 | Yes | No | No | Sometimes |
事务 | Field compares, Read, Write | Version checks, Write | Field compare, Lock, Read, Write | SQL-style |
变化通知 | Historical and current key intervals | Current keys and directories | Current keys and prefixes | Triggers (sometimes) |
用户权限 | Role based | ACLs | ACLs | Varies (per-table GRANT, per-database roles) |
HTTP/JSON API | Yes | No | Yes | Rarely |
成员关系可配置 | Yes | >3.5.0 | Yes | Yes |
最大可靠存储数据量 | 几个GB | 几百兆(有时候也可以存储几个GB) | 几百MBs | TB以上 |
最小线性读时延 | Network RTT | 不支持 | RTT + fsync | Clock barriers (atomic, NTP) |
NewSQL (Cloud Spanner, CockroachDB, TiDB)
ZooKeeper
ZooKeeper和etcd旨在解决相同的问题:分布式系统协调和元数据存储。但是etcd借鉴了ZooKeeper的设计和实现经验,这帮助etcd可以支持像Kubernetes这样的大型分布式系统(站在巨人的肩膀上可以看的更远)。etcd相比ZooKeeper在以下方面得到了改善:
-
支持动态重新配置集群成员角色(ZooKeeper在后面的版本也支持)。
-
高负载下稳定读/写
-
支持多版本并发控制的数据模型
-
可靠的key监控,etcd从不默默删除事件。
-
connection和session解耦
-
提供用于安全分布式共享锁的API
此外,etcd支持的编程语言和框架要比ZooKeeper更加丰富,ZooKeeper使用的是自定义的Jute RPC协议,限制了对其他语言的支持,etcd客户端协议基于流行的gRPC,因此可以支持更多的编程语言比如go,C++,Java等(选择使用开放流行的协议多么重要)。同样,gRPC可以通过HTTP序列化为JSON,因此即使是通用命令行实用程序(例如curl)也可以与etcd通信。由于系统可以从多种选择中进行选择,因此它们是使用本机工具在etcd上构建的,而不是使用一组固定的技术在etcd上构建的(技术生态更加开放)。
选择使用ZooKeeper的应用程序使用etcd都是一种更佳的选择。
Consul
Consul是一个端到端的服务发现框架。Consul提供内置的健康检查,失败检测和DNS服务。除此之外,Consul通过RESTful API提供键-值存储能力。在Consul 1.0中,存储系统在键值操作中无法像etcd或Zookeeper等其他系统那样扩展。 需要数百万个键的系统将遭受高延迟和内存压力。缺少键值API,最明显的是缺少多版本键,条件事务和可靠的流监视API(API不够丰富)。
etcd和Consul解决的问题不同。如果需要一个分布式一致的键-值存储,etcd是一个比Consul更好的选择。如果需要一个端到端的集群服务发现功能,etcd在这方面没有足够的功能,选择使用Kubernetes,Consul或者SmartStack更简单。
NewSQL (Cloud Spanner, CockroachDB, TiDB)
etcd和NewSQL数据库(例如Cockroach,TiDB,Google Spanner)都提供了强大的数据一致性保证和高可用性。但是不同的系统设计参数导致了明显不同的客户端API和性能。
NewSQL数据库旨在提供跨数据中心的水平扩展能力。这些系统通常跨多个一致的复制组(分片)(可能距离很远)对数据进行分区,以存储TB级或更多的数据。这种扩展使得他们不适合做分布式协调工作,因为时延更大而且更新通常依赖本地对图进行更新。NewSQL将数据组织成表,提供具有比etcd更为丰富语义的SQL样式的查询工具,但这以处理,计划和优化查询的额外复杂性为代价。NewSQL的主要目的是数据存储,让专业的人做专业的事情。
简而言之,存储元数据和分布式一致协调选择etcd,如果需要存储大于GB的数据或者需要完整的SQL查询,选择一个NewSQL。
使用etcd存储元数据
etcd在单个一致的复制组中复制所有数据(etcd集群中每个节点都拥有完整的数据)。对于以一致的顺序存储多达几GB的数据,这是最有效的方法。集群状态的每个修改(可能会更改多个键)都从一个单调递增的计数器中分配了一个全局唯一ID(在etcd中称为修订版),以进行排序。由于只有一个复制组,因此修改请求只需通过Raft协议提交即可。通过将共识限制在一个复制组中,etcd使用简单的协议即可获得分布式一致性,同时实现低延迟和高吞吐量。
因为etcd没有数据分片因此etcd的数据不能够水平扩展。相反,NewSQL数据库通常在多个一致的复制组中对数据分片,NewSQL能够存储TB或更多的数据。但是,要为每个修改分配一个全局唯一且递增的ID,每个请求都必须通过复制组之间的附加协调协议。附加协调步骤很可能在全局ID上冲突,从而迫使有序请求重试。对于严格的排序,方法的性能通常比etcd更差。
如果应用程序主要是存储元数据或基于元数据排序实现诸如协调流程的功能,请选择etcd。如果应用需要跨数据中心存储海量数据,而且不严重依赖全局强排序,选择一个NewSQL数据库更加合适。
使用etcd做分布式协调
etcd提供了分布式协调原语,比如事件监听,租约,选举和开箱即用的分布式共享锁。这些分布式原语由etcd的开发人员支持和维护。很多项目将这些原语留给外部库实现,其实是推卸了开发分布式基础软件的责任,使系统不完整(etcd社区的责任心满满)。NewSQL数据库通常期望这些分布式协调原语由第三方编写,ZooKeeper有一个独立的库提供协调原语,Consol虽然提供了原生的锁API,但是做的依然不够优秀。
从理论上讲,可以在提供强大一致性的任何存储系统上构建这些原语。但是,算法往往很微妙,开发一种看起来有效的锁算法很容易,但是由于外部原因功能往往突然就不用了(我们多数工程师都会遇到的,明明好好的咋到你这里就不好用了呢)。此外,etcd支持的其他原语(例如事务性存储器)取决于etcd的MVCC数据模型, 简单的强一致性是不够的。
对于分布式协调,选择etcd可以帮助避免操作上的麻烦并节省工作量。
网友评论