一些比较

zk之类的集群一般3到5节点组成。多于半数节点可用,整个系统对外是可用状态

go技术栈,应用 etcd/consul 比zk成熟和应用广泛

etcd

etcd 3 优化

量级

etcd 2 数十万key、etcd3 百万到千万key

主要因一致性系统基于log的复制,log不能无限增长,某一时刻要做完整snapshot且存到磁盘后才能将之前的log丢弃

每次存完整snasphot没效率,但一致性系统设计增量snapshot及传输同步大量数据非常繁琐

etcd 3对raft和存储重构,更好支持增量snapshot和传相对较大的snapshot


大规模watch,减小每个watch消耗

  1. HTTP/2的multiple stream per tcp connection,同一client的不同watch,share同一个tcp connection
  2. 同用户的不同watch只使用一个go routine

3台8核云服务器,etcd 3每秒数万次写和十万次读

etcd 2仅保存了1000个历史更改,watch过慢就无法得到之前的变更

etcd 3为了支持多纪录,采用历史记录为主索引的存储结构。可以存储上十万个纪录,进行快速查询并且支持根据用户的要求进行compaction

理念

etcd着重于go stack和cloud infra领域

etcd 对CoreOS没有依赖,性能没折扣

与zk临时节点相比,etcd 3支持lease,可lease到多key,到所有key自动删除

etcd支持稳定的watch而不是zk 的one time trigger watch,原因:很多调度系统需要得到完整历史记录

Consul是个full stack的工具

etcd只是一个简单的一致性kv,认为能把一致性kv这件事情完整的做好已经不容易了 希望上层系统可以在etcd上搭建,而不是让etcd本身服务最终用户

某些程度上而言,Consul并不着重保证自身的稳定性和可靠性。HashiCorp自己的调度系统nomad也并没有采用Consul。这些差别导致了很多设计、实现上的不同

etcd Masters失效后,默认timeout 1秒,2秒内可以选出新主恢复写。网络不稳定或者服务器忙,可以提高到5秒,10秒内选出

etcd API接口基于HTTP,client在etcd集群保持long-polling

逻辑结构

zk是树结构,而etcd从逻辑上来看就是一个k-v结构。但仍旧可以模拟出目录,表达父子关系

etcd本质上是一个有序的k-v存储

/a/b,/a/b/c,/a/b/d在存储中顺序排列,定位到key=/a/b并依次顺序向后扫描,就会遇到/a/b/c与/a/b/d这两个孩子,一样可以实现父子目录关系

临时节点

zk,客户端与zk server间的session会话没有中断(过期),临时节点就存在 当客户端掉线一段时间,对应的zk session会过期,临时节点自动删除

etcd支持lease租约机制。其实就是etcd支持申请定时器,比如:申请TTL=10秒的lease(租约),返回lease ID标识定时器。set key同时携带lease ID,就实现了一个自动过期的key。一个lease可以关联给任意多的Key,当lease过期后所有关联的key都将被自动删除

实现临时节点,首先申请一个TTL=N的lease,然后set一个key with lease作为自己的临时节点,在程序中定时的为lease(租约)进行续约,也就是重置TTL=N,这样关联的key就不会过期了

事件模型

zk getChildrenAndWatch获取目录下所有在线节点,并同时原子注册了一个观察器。孩子有变动的时候,就发一个通知事件给客户端(同时关闭观察器),再调用getChildrenAndWatch

获取并观察->收到变化事件->获取并观察->收到变化事件->….,如此往复

zk 事件模型非常可靠,不会出现发生了更新而客户端不知道的情况,特点:

  • 事件不包含数据,仅仅是通知变化
  • 多次连续的更新,通知会合并成一个;即,客户端收到通知再次拉取数据,会跳过中间的多个版本,只拿到最新数据。

这些特点并不是缺点,因为一般应用只关注最新状态,并不关注中间的连续变化

etcd事件包含数据,通常连续的更新不会被合并通知,而是逐条通知到客户端

k-v

etcd 内存中维护了一个btree,有序,key是用户key,用户value保存在磁盘中,节省内存 K-V存储引擎 bbolt

ZooKeeper vs Eureka

zk 基于CP,不保证高可用,正在选主,或集群半数以上机器不可用,无法获得数据

Eureka基于AP,保证高可用,即使所有机器都挂了,也能拿到本地缓存的数据

注册中心配置不常变,发版和机器故障时会变。对不经常变动的配置来说,CP不合适,AP遇到问题时可牺牲一致性保证可用性,返回旧数据,缓存数据

所以理论上Eureka是更适合作注册中心。而现实环境中大部分项目用zk,因为集群不够大,且基本不会遇到注册中心机器一半以上都挂了的情况。所以实际上也没什么大问题

Eureka 机制

Eureka 集群解决单点问题不同于zk选举leader,用Peer to Peer对等通信。中心化的架构,无master/slave区分。节点彼此互相注册提高可用性,每节点添加一或多个serviceUrl指向其他节点

Eureka Server一定时间内没有接到某个服务实例的心跳,注销该实例(默认为90秒,eureka.instance.lease-expiration-duration-in-seconds)

Eureka Server节点短时间内丢失过多的心跳时(比如发生了网络分区故障),节点进入自我保护模式,不再注销服务实例

设计哲学,宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例

ref

Zookeeper,etcd,consul内部机制和分布式锁和选主实现的比较 https://yq.aliyun.com/articles/70566