共计 3848 个字符,预计需要花费 10 分钟才能阅读完成。
作者:王雷
etcd 是什么
etcd 是云原生架构中重要的根底组件,由 CNCF 孵化托管。ETCD 是用于共享配置和服务发现的分布式,一致性的 KV 存储系统,是 CoreOS 公司发动的一个开源我的项目,受权协定为 Apache。etcd 基于 Go 语言实现,次要用于共享配置,服务发现,集群监控,leader 选举,分布式锁等场景。在微服务和 Kubernates 集群中不仅能够作为服务注册发现,还能够作为 key-value 存储的中间件。
提到键值存储系统,在大数据畛域利用最多的当属 ZOOKEEPER,而 ETCD 能够算得上是后起之秀了。在我的项目实现,一致性协定易了解性,运维,平安等多个维度上,ETCD 相比 Zookeeper 都占据劣势。
ETCD vs ZK
| ETCD | ZK |
---|---|---|
一致性协定 | Raft 协定 | ZAB(类 Paxos 协定) |
运维方面 | 不便运维 | 难以运维 |
我的项目活跃度 | 沉闷 | 没有 etcd 沉闷 |
API | ETCD 提供 HTTP+JSON, gRPC 接口,跨平台跨语言 | ZK 须要应用其客户端 |
拜访平安方面 | ETCD 反对 HTTPS 拜访 | ZK 在这方面不反对 |
etcd 的架构
etcd 是一个分布式的、牢靠的 key-value 存储系统,它用于存储分布式系统中的要害数据,这个定义十分重要。
通过上面这个指令,理解一下 etcd 命令的执行流程,其中 etcdctl:是一个客户端,用来操作 etcd。
etcdctl put key test
通常 etcd 都是以集群的形式来提供服务的,etcdctl 操作命令的时候,会对应到 leader 当中的 gRPC Server
gRPC Server
用来接管客户端具体的申请进行解决,然而不仅仅是解决客户端的连贯,它同时负责解决集群当中节点之间的通信。
wal: Write Ahead Log(预写式日志)
etcd 的数据存储形式。除了在内存中存有所有数据的状态以及节点的索引以外,etcd 就通过 WAL 进行长久化存储。WAL 中,所有的数据提交前都会当时记录日志。实现事务日志的规范办法;执行写操作前先写日志,跟 mysql 中 redo 相似,wal 实现的是程序写。
当执行 put 操作时,会批改 etcd 数据的状态,执行具体的批改的操作,wal 是一个日志,在批改数据库状态的时候,会先批改日志。put key test 会在 wal 记录日志,而后会进行播送,播送给集群当中其余的节点设置 key 的日志。其余节点之后会返回 leader 是否批准数据的批改,当 leader 收到一半的申请,就会把值刷到磁盘中。
snapshot
etcd 避免 WAL 文件过多而设置的快照,用于存储某一时刻 etcd 的所有数据。Snapshot
和 WAL
相结合,etcd
能够无效地进行数据存储和节点故障复原等操作。
boltdb
相当于 mysql 当中的存储引擎,etcd 中的每个 key 都会创立一个索引,对应一个 B + 树。
etcd 重要的个性
•存储:数据分层存储在文件目录中,相似于咱们日常应用的文件系统;
•Watch 机制:Watch 指定的键、前缀目录的更改,并对更改工夫进行告诉;
•平安通信:反对 SSL 证书验证;
•高性能:etcd 单实例能够反对 2K/s 读操作,官网也有提供基准测试脚本;
•统一牢靠:基于 Raft 共识算法,实现分布式系统外部数据存储、服务调用的一致性和高可用性;
•Revision 机制:每个 Key 带有一个 Revision 号,每进行一次事务便加一,因而它是全局惟一的,如初始值为 0,进行一次 Put 操作,Key 的 Revision 变为 1,同样的操作,再进行一次,Revision 变为 2;换成 Key1 进行 Put 操作,Revision 将变为 3。这种机制有一个作用,即通过 Revision 的大小就可晓得写操作的程序,这对于实现偏心锁,队列非常无益;
•lease 机制:lease 是分布式系统中一个常见的概念,用于代表一个分布式租约。典型状况下,在分布式系统中须要去检测一个节点是否存活的时,就须要租约机制。
首先创立了一个 10s 的租约,如果创立租约后不做任何的操作,那么 10s 之后,这个租约就会主动过期。接着将 key1 和 key2 两个 key value 绑定到这个租约之上,这样当租约过期时 etcd 就会主动清理掉 key1 和 key2,使得节点 key1 和 key2 具备了超时主动删除的能力。
如果心愿这个租约永不过期,须要周期性的调用 KeeyAlive 办法刷新租约。比如说须要检测分布式系统中一个过程是否存活,能够在过程中去创立一个租约,并在该过程中周期性的调用 KeepAlive 的办法。如果一切正常,该节点的租约会统一放弃,如果这个过程挂掉了,最终这个租约就会主动过期。
类比 redis 的 expire,redis expore key ttl,如果 key 过期的话,到了过期工夫,redis 会删除这个 key。etcd 的实现:将过期工夫雷同的 key 全副绑定一个全局的对象,去治理过期,etcd 只须要检测这个对象的过期。通过多个 key 绑定在同一个 lease 的模式,咱们能够将超工夫类似的 key 聚合在一起,从而大幅减小租约刷新的开销,在不失灵活性同时可能大幅提高 etcd 反对的应用规模。
在引擎中的场景
服务注册发现
etcd 基于 Raft 算法,可能无力的保障分布式场景中的一致性。各个服务启动时注册到 etcd 上,同时为这些服务配置键的 TTL 工夫。注册到 etcd 上的各个服务实例通过心跳的形式定期续租,实现服务实例的状态监控。服务提供方在 etcd 指定的目录(前缀机制反对)下注册服务,服务调用方在对应的目录下查问服务。通过 watch 机制,服务调用方还能够监测服务的变动。
引擎服务蕴含两大模块,一个是 master 服务,一个是调度服务。
master 服务
master 服务启动胜利后,向 etcd 注册服务,并且定时向 etcd 发送心跳
server, err := NewServiceRegister(key, serviceAddress, 5)
if err != nil {logging.WebLog.Error(err)
}
定时向 etcd 发送心跳
// 设置续租 定期发送需要申请
leaseRespChan, err := s.cli.KeepAlive(context.Background(), resp.ID)
调度服务
调度服务作为服务的消费者,监听服务目录:key=/publictest/pipeline/
// 从 etcd 中订阅前缀为 "/pipeline/" 的服务
go etcdv3client.SubscribeService("/publictest/pipeline/", setting.Conf.EtcdConfig)
监听 put 和 delete 操作,同时在本地保护 serverslist,如果有 put 或者 delete 操作,会更新本地的 serverslist
客户端发现指客户端间接连贯注册核心,获取服务信息,本人实现负载平衡,应用一种负载平衡策略发动申请。劣势能够定制化发现策略与负载平衡策略,劣势也很显著,每一个客户端都须要实现对应的服务发现和负载平衡。
watch 机制
etcd 能够 Watch
指定的键、前缀目录的更改,并对更改工夫进行告诉。BASE 引擎中,缓存的革除策略借助 etcd 来实现。
缓存过期策略:在编译减速的实现中,每个须要缓存的我的项目都有对应的缓存 key,通过 etcd 监控 key,并且设置过期工夫,例如 7 天,如果在 7 天之内再次命中 key,则通过 lease 进行续约;7 天之内 key 都没有被应用,key 就会过期删除,通过监听对应的前缀,在过期删除的时候,调用删除缓存的办法。
storage.Watch("cache/",
func(id string) {//do nothing},
func(id string) {CleanCache(id)
})
除此之外,引擎在流水线勾销和人工确认超时的场景中,也应用到了 etcd 的 watch 机制,监听某一个前缀的 key,如果 key 产生了变动,进行相应的逻辑解决。
集群监控与 leader 选举机制
集群监控:通过 etcd 的 watch 机制,当某个 key 隐没或变动时,watcher 会第一工夫发现并告知用户。节点能够为 key 设置租约(TTL),比方每隔 30 s 向 etcd 发送一次心跳续约,使代表该节点的 key 放弃存活,一旦节点故障,续约进行,对应的 key 将生效删除。如此,通过 watch 机制就能够第一工夫检测到各节点的衰弱状态,以实现集群的监控要求。
Leader 竞选:应用分布式锁,能够很好地实现 Leader 竞选(抢锁胜利的成为 Leader)。Leader 利用的经典场景是在搜寻零碎中建设全量索引。如果每个机器别离进行索引建设,不仅耗时,而且不能保障索引的一致性。通过在 etcd 实现的锁机制竞选 Leader,由 Leader 进行索引计算,再将计算结果散发到其它节点。
相似 kafka 的 controller 选举,引擎的调度服务启动,所有的服务都注册到 etcd 的 /leader 上面,其中最先注册胜利的节点成为 leader 节点,其余节点主动变成 follow。
leader 节点负责从 redis 中获取工作,依据负载平衡算法,将工作派发给对应的 go master 服务。
follow 节点监听 leader 节点的状态,如果 leader 节点服务不可用,对应节点删除,follow 节点会从新抢占,成为新的 leader 节点。
同时 leader 设置在 etcd 中的 leader 标识设置过期工夫为 60s,leader 每隔 30s 更新一次。follow 每隔 30s 到 etcd 中通告本人存活,并查看 leader 存活。