etcd基本原理

  etcd 是一个分布式的、可靠的 key-value 存储系统,它用于存储分布式系统中的关键数据

  一个 etcd 集群,通常会由奇数个节点组成,多个节点之间,通过一个叫做 Raft 一致性算法的方式完成分布式一致性协同,算法会选举出一个主节点作为 leader,由 leader 负责数据的同步与数据的分发,当 leader 出现故障后,系统会自动地选取另一个节点成为 leader,并重新完成数据的同步与分发。客户端在众多的 leader 中,仅需要选择其中的一个就可以完成数据的读写。

  在 etcd 整个的架构中,有一个非常关键的概念叫做 quorum,quorum 的定义是 =(n+1)/2,也就是说超过集群中半数节点组成的一个团体,只要有任意一个 quorum 存活,其中一定存在某一个节点,它包含着集群中最新的数据,一致性算法就可以在一个 quorum 之间采用这份最新的数据去完成数据的同步,从而保证整个集群向前衍进的过程中其数据保持一致。

  5 组常用的etcd 接口:

    第一组是 Put 与 Delete。上图可以看到 put 与 delete 的操作都非常简单,只需要提供一个 key 和一个 value,就可以向集群中写入数据了,那么在删除数据的时候,只需要提供 key 就可以了;

    第二组操作是查询get操作。查询操作 etcd 支持两种类型的查询:第一种是指定单个 key 的查询,第二种是指定的一个 key 的范围;

    第三组操作:etcd 启动了 Watch 的机制,也就是我们前面提到的用于实现增量的数据更新,watch 也是有两种使用方法,第一种是指定单个 key 的 Watch,另一种是指定一个 key 的前缀。在实际应用场景的使用过程中,经常采用第二种;

    第四组:事务操作,可以通过指定某些条件,当条件成立的时候执行一组操作。当条件不成立的时候执行另外一组操作;

    第五组是 Leases 接口。Leases 接口是分布式系统中常用的一种设计模式,后面会具体介绍。

  etcd 中有个 term 任期的概念,代表的是整个集群 Leader 的标志。当集群发生 Leader 切换,term 的值就会 +1。

  版本号 revision,revision 代表的是全局数据的版本。当数据发生变更,包括创建、修改、删除,revision 对应的都会 +1。在任期内,revision 都可以保持全局单调递增的更改。正是 revision 的存在才使得 etcd 既可以支持数据的 MVCC,也可以支持数据的 Watch。  

  对于每一个 KeyValue 数据,etcd 中都记录了三个版本:

    第一个版本叫做 create_revision,是 KeyValue 在创建的时候生成的版本号;

    第二个叫做 mod_revision,是其数据被操作的时候对应的版本号;

    第三个 version 就是一个计数器,代表了 KeyValue 被修改了多少次。

  在 etcd 中,支持对同一个 Key 发起多次数据修改。因为已经知道每次数据修改都对应一个版本号,多次修改就意味着一个 key 中存在多个版本,在查询数据的时候可以通过不指定版本号查询,这时 etcd 会返回该数据的最新版本。当我们指定一个版本号查询数据后,可以获取到一个 Key 的历史版本。

  在 watch 的时候指定数据的版本,创建一个 watcher,并通过这个 watcher 提供的一个数据管道,能够获取到指定的 revision 之后所有的数据变更。如果指定的 revision 是一个旧版本,可以立即拿到从旧版本到当前版本所有的数据更新。并且,watch 的机制会保证 etcd 中,该 Key 的数据发生后续的修改后,依然可以从这个数据管道中拿到数据增量的更新。

  在 etcd 中所有的数据都存储在b+tree 中。b+tree 是保存在磁盘中,并通过 mmap 的方式映射到内存用来查询操作。

    一个 b+tree维护着 revision 到 value 的映射关系

    一个 b+tree管理着 key 到 revision 的映射关系

    一个数据是有多个版本的;

    在 etcd 持续运行过程中会不断的发生修改,意味着 etcd 中内存及磁盘的数据都会持续增长。这对资源有限的场景来说是无法接受的。因此在 etcd 中会周期性的运行一个 Compaction 的机制来清理历史数据。对于一个 Key 的历史版本数据,可以选择清理掉。

  etcd 的 transaction 机制比较简单,基本可以理解为一段 if-else 程序,在 if 中可以提供多个操作。在 etcd 内部会保证整个事务操作的原子性。也就是说 If 操作所有的比较条件,其看到的视图,一定是一致的。同时它能够确保在争执条件中,多个操作的原子性不会出现 etcd 仅执行了一半的情况。

  在 etcd 中,允许将多个 key 关联在统一的 lease 之上,如果大量的键都绑定在同一个租约对象上,并且每个键都频繁地更新这个租约,可能会对 etcd 产生很大的压力。合理设置租约持续时间,分散租约,将多个更新操作合并为单个请求,可以减少网络开销和 etcd 的负载。

使用场景

  元数据存储-Kubernetes, Kubernetes 将自身所用的状态设备存储在 etcd 中,Kubernetes 系统自身不需要再树立复杂的状态流转,因此自身的系统设立架构也得到了大幅的简化。

  Service Discovery,在进程内部启动之后,可以将自身所在的地址注册到 etcd。从而使得 API 网关能够通过 etcd 及时感知到后端进程的地址,这样当后端进程发生故障迁移的时候,会重新注册到 etcd 中,使得 API 网关能够及时地感知到新的集群地址。同时,因为 etcd 提供的 Lease 操作,可以及时感知到进程状态的变化,如果进程运行过程中死掉了,那么网关可以及时感知到进程状态的变化,从而将流量自动地切到其他的进程。

  leader election,被选主的 Leader 可以将自己的 IP 注册到 etcd 中,使得 Slave 节点能够及时获取到当前组件的地址,从而使得系统按照之前单个 Master 节点的方式继续工作。当 Leader 节点发生异常之后,通过 etcd 能够选取出一个新的节点成为主节点,并且注册新的 IP 之后,Slave 又能够拉取新的主节点的 IP,从而会继续恢复服务。

  分布式系统并发控制,通过 etcd 去实现一个分布式的信号量,并且它支持能够自动地剔除掉故障节点。如果进程的运行周期比较长,我们可以将进程运行过程中的一些状态数据存储到 etcd,从而使得当进程故障之后且需要恢复到其他地方时,能够从 etcd 中去恢复一些执行状态,而不需要重新去完成整个的计算逻辑,以此来加速整个任务的执行效率。

 

posted @ 2023-11-02 16:09  花都八达鸟  阅读(324)  评论(0)    收藏  举报