工作中遇到了一些问题,发现对etcd基础知识的欠缺导致在一些理解上面出现了一些偏差。这篇笔记,花了3小时的时间,初步查了一些资料后,结合自己的理解,做的一些整理。
一家直言,并没有什么权威性,仅仅是自己的理解。如果需要权威,https://github.com/etcd-io/etcd/blob/master/Documentation/learning/why.md
这个才是王道。
此外,梳理完以后,自身对etcd有了大概了解,但是不深入,在理解上也许会有些矛盾,欢迎探讨。
正文开始。
在Core OS和Kubernetes的发展中,etcd作为**高可用、强一致性的服务发现组件**被引用到其中。
etcd的产生主要适用于:(看起来和ZooKeeper很像,具体区别后续研究讨论)
总结起来,etcd可以实现的功能Zookeeper基本上都可以。但是相比之下,etcd有如下优势:
相比之下ZooKeeper的缺点:
总结:
etcd是基于Raft强一致性算法的分布式数据存储仓库。
其中分布式系统中,数据可以分为两种,即控制数据,应用数据。使用etcd默认场景就是控制数据的存储。应用数据也可以存储,但是要保证,该应用数据有数据量小,更新访问频率频繁的特性。
所以,grpc的服务发现便是用etcd实现的,符合存储控制数据的etcd默认适用场景。(此处有两个疑问,数据量小,参考值多少?更新访问频繁?有多频繁,就目前而言,每个etcd实例支持每秒1000次写操作)
引用etcd官方文档中的一句话,来说明etcd的作用。
Distributed systems use etcd as a consistent key-value store for configuration management, service discovery, and coordinating distributed work. --在分布式系统中,通过etcd的强一致性k-v数据存储来实现,配置管理,服务发现,分布式任务调度。
在分布式系统中,有专门的进程在监听某一TCP或UDP端口,并且支持根据服务名查询到对应服务的IP和端口。
此外,服务发现还分为两种模式,即客户端服务发现与服务端服务发现,这里打个tag后续补充
服务发现,有三大基础缺一不可(一家之言)
1. 一个高可用,强一致性的服务目录(基于Raft算法的etcd天然支持)
> 高可用计算公式:
A=MTBF/MTBF+MTTR
>A:可用性.>平均故障时间(MTBF):Mean Time Between Failure,即相邻两次故障之间的平均工作时间。
>平均修复时间(MTTR):Mean Time To Repair,即数据库系统由故障状态转为工作状态所花费的修理时间的平均值。
2. 服务注册和服务健康状况的监控机制(用户可以在 etcd 中注册服务,并且对注册的服务设置key TTL,定时保持服务的心跳以达到监控健康状态的效果。扩展一下:目前所使用的GPRC服务都会配置一个探活端口,也许etcd就是使用这个端口用于探活)
3. 查找和链接服务的机制(通过在 etcd 指定的主题下注册的服务也能在对应的主题下查找到。为了确保连接,我们可以在每个服务机器上都部署一个 Proxy 模式的 etcd,这样就可以确保能访问 etcd 集群的服务都能互相连接)。
- 服务查找:通过ZK树状目录的思路,很好理解。
- Proxy模式的etcd,这点属于盲区,后续补充
服务发现示意图
基于etcd的服务发现流程描述
其实很简单,在某一服务启动时,就会在注册中心创建服务目录,在该目录下存储着服务的所有实例的ip和端口。请求发起时,client端会从regist center获取对应ip端口,在结合对应负载均衡策略,选择Service Instance。在此场景中,使用了etcd的数据存储特性完成。
在分布式系统中常用的一种模型。etcd和zk同样也支持该模型。相对与MQ来说,etcd和zk更加适用于集群中应用的统一配置管理。例如动态数据源,便是通过ZK实现数据源信息变更的监听机制。就grpc服务的服务发现机制来说,etcd也能实现类似zk的功能。
订阅发布模型的使用场景,可以尝试的理解为,某一组建的统一配置中心。(apllo底层搞不清楚是什么实现的。搞不好核心的控制数据存储就是用的etcd或者zk)
利用etcd可监控应用健康状态的特性与每个etcd节点都可以独立提供服务的特点。可以利用etcd维护一个负载均衡节点表,根据该节点表,即可找到available节点,在此基础上做负载均衡策略。(类似zookeeper来维持kafka的负载均衡)
通过注册与异步通知机制,实现分布式环境下不同系统之间的通知与协调,从而对数据变更做到实时处理。实现方式通常是这样:不同系统都在 etcd 上对同一个目录进行注册,同时设置 Watcher 观测该目录的变化(如果对子目录的变化也有需要,可以设置递归模式),当某个系统更新了 etcd 的目录,那么设置了 Watcher 的系统就会收到通知,并作出相应处理。
得益于基于Raft算法的数据强一致性特性。搞分布式锁这种需要全局唯一性的值的实现,etcd实现起来很容易(没实现过,不知道和基于redis的有啥区别。)锁的两种使用方式,保持独占(悲观锁),控制时序。
分布式队列的常规用法与场景五中所描述的分布式锁的控制时序用法类似,即创建一个先进先出的队列,保证顺序。
另一种比较有意思的实现是在保证队列达到某个条件时再统一按顺序执行。这种方法的实现可以在 /queue 这个目录中另外建立一个 /queue/condition 节点。
通过 etcd 来进行监控实现起来非常简单并且实时性强。
1. 前面几个场景已经提到 Watcher 机制,当某个节点消失或有变动时,Watcher 会第一时间发现并告知用户。
2. 节点可以设置TTL key,比如每隔 30s 发送一次心跳使代表该机器存活的节点继续存在,否则节点消失。
这样就可以第一时间检测到各节点的健康状态,以完成集群的监控要求。
另外,使用分布式锁,可以完成 Leader 竞选。这种场景通常是一些长时间 CPU 计算或者使用 IO 操作的机器,只需要竞选出的 Leader 计算或处理一次,就可以把结果复制给其他的 Follower。从而避免重复劳动,节省计算资源。
这个的经典场景是搜索系统中建立全量索引。如果每个机器都进行一遍索引的建立,不但耗时而且建立索引的一致性不能保证。通过在 etcd 的 CAS 机制同时创建一个节点,创建成功的机器作为 Leader,进行索引计算,然后把计算结果分发到其它节点。
根据这7中适用场景可以归纳出etcd有以下应用特性(后续补充)
1. 基于Raft算法的强数据一致性特点。可用于分布式系统中,全局性质变量的存储。
2. key TTL(Time To Live)特性(类比redis的key有效时间),实现服务的健康状态监控(根据目前知识推测,是不是key失效以后,所有的订阅者都会接收到该消息?如果是的话,非固定时常的延迟队列既可以利用该特性实现)
3. Topic的概念。(借用kafka的Topic概念,consumer监听的是topic,即监听该topic的所有consumer都可以收到消息。)
4. Watcher机制。