etcd简介

etcd是开源的、高可用的分布式key-value存储系统,可用于配置共享和服务的注册和发现,它专注于:

  • 简单:定义清晰、面向用户的API(gRPC)

  • 安全:可选的客户端TLS证书自动认证

  • 快速:支持每秒10,000次写入

  • 可靠:基于Raft算法确保强一致性

etcd与redis差异

etcd和redis都支持键值存储,也支持分布式特性,redis支持的数据格式更加丰富,但是他们两个定位和应用场景不一样,关键差异如下:

  • redis在分布式环境下不是强一致性的,可能会丢失数据,或者读取不到最新数据

  • redis的数据变化监听机制没有etcd完善

  • etcd强一致性保证数据可靠性,导致性能上要低于redis

  • etcd和ZooKeeper是定位类似的项目,跟redis定位不一样

为什么用 etcd 而不用ZooKeeper?

相较之下,ZooKeeper有如下缺点:

  • 复杂:ZooKeeper的部署维护复杂,管理员需要掌握一系列的知识和技能;而 Paxos 强一致性算法也是素来以复杂难懂而闻名于世;另外,ZooKeeper的使用也比较复杂,需要安装客户端,官方只提供了 Java 和 C 两种语言的接口。

  • 难以维护:Java 编写。这里不是对 Java 有偏见,而是 Java 本身就偏向于重型应用,它会引入大量的依赖。而运维人员则普遍希望保持强一致、高可用的机器集群尽可能简单,维护起来也不易出错。

  • 发展缓慢:Apache 基金会项目特有的“Apache Way”在开源界饱受争议,其中一大原因就是由于基金会庞大的结构以及松散的管理导致项目发展缓慢。

而 etcd 作为一个后起之秀,其优点也很明显。

  • 简单:使用 Go 语言编写部署简单;使用 HTTP 作为接口使用简单;使用 Raft 算法保证强一致性让用户易于理解。

  • 数据持久化:tcd 默认数据一更新就进行持久化。

  • 安全:etcd 支持 SSL 客户端安全认证。

单机部署

(1)到etcd的github地址,下载最新的安装包(目前最新版本:v3.4.7)

下载地址:https://github.com/etcd-io/etcd/releases/

(2)解压,把etcdetcdctl文件复制到已经配置了环境变量的目录中

  • 方法一:把etcdetcdctl文件复制到GOBIN目录下。

  • 方法二:在环境变量里添加etcdetcdctl文件所在的目录。

(3)验证是否安装成功

$ etcd --version
etcd Version: 3.4.7
Git SHA: e694b7bb0
Go Version: go1.12.17
Go OS/Arch: linux/amd64

正常显示etcd版本信息,则证明安装成功。

API学习

etcdctl用于与etcd交互的控制台程序。API版本可以通过ETCDCTL_API环境变量设置为2或3版本。默认情况下,v3.4以上的etcdctl使用v3 APIv3.3及更早的版本默认使用v2 API

注意:用v2 API创建的任何key将不能通过v3 API查询。同样,用v3 API创建的任何key将不能通过v2 API查询。

运行etcd,在终端输入:etcd

在另一个终端运行ctcdctl测试。

#查看默认API版本
$ etcdctl version
etcdctl version: 3.4.7
API version: 3.4 #v3 API #写入key:/test/foo value:hello etcd (双引号可去掉)
$ etcdctl put /test/foo "hello etcd"
OK
$ etcdctl get /test/foo
/test/foo
hello etcd #手动切换到v2 API
$ export ETCDCTL_API=2
$ etcdctl --version
etcdctl version: 3.4.7
API version: 2 $ etcdctl get /test/foo
Error: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint #查询不到/test/foo的值

写入key

$ etcdctl put foo bar
OK

读取key值

$ etcdctl get foo
foo
bar #只是获取值
$ etcdctl get foo --print-value-only
bar
$ etcdctl put foo1 bar1
$ etcdctl put foo2 bar2
$ etcdctl put foo3 bar3 #获取从foo到foo3的值,不包括foo3
$ etcdctl get foo foo3 --print-value-only
bar
bar1
bar2 # 获取前缀为foo的值
$ etcdctl get --prefix foo --print-value-only
bar
bar1
bar2
bar3 #获取符合前缀的前两个值
$ etcdctl get --prefix --limit=2 foo --print-value-only
bar
bar1

删除key

#删除foo
$ etcdctl del foo
1 #删除foo到foo2,不包括foo2
$ etcdctl del foo foo2
1
#删除key前缀为foo的
$ etcdctl del --prefix foo
2

监视值变化

#监视foo单个key
$ etcdctl watch foo
#另一个控制台执行: etcdctl put foo bar
PUT
foo
bar #同时监视多个值
$ etcdctl watch -i
$ watch foo
$ watch zoo
# 另一个控制台执行: etcdctl put foo bar
PUT
foo
bar
# 另一个控制台执行: etcdctl put zoo val
PUT
zoo
val #监视foo前缀的key
$ etcdctl watch --prefix foo
#另一个控制台执行: etcdctl put foo1 bar1
PUT
foo1
bar1
#另一个控制台执行: etcdctl put fooz1 barz1
PUT
fooz1
barz1

设置租约(Grant leases)

当一个key被绑定到一个租约上时,它的生命周期与租约的生命周期绑定。

#设置60秒后过期时间
$ etcdctl lease grant 60
lease 32695410dcc0ca06 granted with TTL(60s) #把foo和租约绑定,设置成60秒后过期
$ etcdctl put --lease=32695410dcc0ca06 foo bar
OK
$ etcdctl get foo
foo
bar #60秒后,获取不到foo
$ etcdctl get foo
#返回空

主动撤销租约(Revoke leases)

通过租赁ID(此处指:32695410dcc0ca06)撤销租约。撤销租约将删除其所有绑定的key

$ etcdctl lease grant 60
lease 32695410dcc0ca06 granted with TTL(60s)
$ etcdctl put foo bar --lease=32695410dcc0ca06
OK #主动撤销租约
$ etcdctl lease revoke 32695410dcc0ca06
lease 32695410dcc0ca06 revoked $ etcdctl get foo
#返回空

续租约(Keep leases alive)

通过刷新其TTL来保持租约的有效,使其不会过期。

#设置60秒后过期租约
$ etcdctl lease grant 60
lease 32695410dcc0ca06 granted with TTL(60s) #把foo和租约绑定,设置成60秒后过期
$ etcdctl put foo bar --lease=32695410dcc0ca06 #续租约,自动定时执行续租约,续约成功后每次租约为60秒
$ etcdctl lease keep-alive 32695410dcc0ca06
lease 32695410dcc0ca06 keepalived with TTL(60)
lease 32695410dcc0ca06 keepalived with TTL(60)
lease 32695410dcc0ca06 keepalived with TTL(60)
...

获取租约信息(Get lease information)

获取租约信息,以便续租或查看租约是否仍然存在或已过期

#设置500秒TTL
$ etcdctl lease grant 500
lease 694d5765fc71500b granted with TTL(500s) #keyzoo1绑定694d5765fc71500b租约
$ etcdctl put zoo1 val1 --lease=694d5765fc71500b
OK #查看租约信息,remaining(132s)剩余有效时间132秒;--keys获取租约绑定的key
$ etcdctl lease timetolive --keys 694d5765fc71500b
lease 694d5765fc71500b granted with TTL(500s), remaining(132s), attached keys([zoo1])

值得注意的地方,一个租约可以绑定多个key

$ etcdctl lease grant 500
lease 694d5765fc71500b granted with TTL(500s) $ etcdctl put zoo1 val1 --lease=694d5765fc71500b
OK $ etcdctl put zoo2 val2 --lease=694d5765fc71500b
OK

当租约过期后,所有key值会被删除。

当一个租约只绑定了一个key时,想删除这个key,最好的办法是撤销它的租约,而不是直接删除这个key

看下面这个例子:

#方法一:直接删除`key`
#设置租约并绑定zoo1
$ etcdctl lease grant 60
lease 694d71f80ed8bf1e granted with TTL(60s)
$ etcdctl put zoo1 val1 --lease=694d71f80ed8bf1e
OK #续租约
$ etcdctl lease keep-alive 694d71f80ed8bf1e
lease 694d71f80ed8bf1e keepalived with TTL(60) #另一个控制台执行:etcdctl del zoo1 #单纯删除key后,续约操作还会一直进行,造成内存泄露
lease 694d71f80ed8bf1e keepalived with TTL(60)
lease 694d71f80ed8bf1e keepalived with TTL(60)
lease 694d71f80ed8bf1e keepalived with TTL(60)
...
方法二:撤销`key`的租约
#设置租约并绑定zoo1
$ etcdctl lease grant 60
lease 694d71f80ed8bf1e granted with TTL(60s)
$ etcdctl put zoo1 val1 --lease=694d71f80ed8bf1e
OK #续租约
$ etcdctl lease keep-alive 694d71f80ed8bf1e
lease 694d71f80ed8bf1e keepalived with TTL(60)
lease 694d71f80ed8bf1e keepalived with TTL(60) #另一个控制台执行:etcdctl lease revoke 694d71f80ed8bf1e #续约操作并退出
lease 694d71f80ed8bf1e expired or revoked.

当租约没有绑定key时,应主动把它撤销掉。

应用场景

根据以上特性和API,etcd有应用场景以下应用场景:

场景一:服务发现

服务发现要解决的也是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务,要如何才能找到对方并建立连接。本质上来说,服务发现就是想要了解集群中是否有进程在监听 udp 或 tcp 端口,并且通过名字就可以查找和连接。

场景二:配置中心

etcd的应用场景优化都是围绕存储的东西是“配置” 来设定的。

  • 配置的数据量通常都不大,所以默认etcd的存储上限是1GB
  • 配置通常对历史版本信息是比较关心的,所以etcd会保存 版本(revision) 信息
  • 配置变更是比较常见的,并且业务程序会需要实时知道,所以etcd提供了watch机制,基本就是实时通知配置变化
  • 配置的准确性一致性极其重要,所以etcd采用raft算法,保证系统的CP
  • 同一份配置通常会被大量客户端同时访问,针对这个做了grpc proxy对同一个key的watcher做了优化
  • 配置会被不同的业务部门使用,提供了权限控制和namespace机制

场景三:负载均衡

此处指的负载均衡均为软负载均衡,分布式系统中,为了保证服务的高可用以及数据的一致性,通常都会把数据和服务部署多份,以此达到对等服务,即使其中的某一个服务失效了,也不影响使用。由此带来的坏处是数据写入性能下降,而好处则是数据访问时的负载均衡。因为每个对等服务节点上都存有完整的数据,所以用户的访问流量就可以分流到不同的机器上。

场景四:分布式锁

因为 etcd 使用 Raft 算法保持了数据的强一致性,某次操作存储到集群中的值必然是全局一致的,所以很容易实现分布式锁。

场景五:集群监控与 Leader 竞选

通过 etcd 来进行监控实现起来非常简单并且实时性强。

  • 前面几个场景已经提到 Watcher 机制,当某个节点消失或有变动时,Watcher 会第一时间发现并告知用户。
  • 节点可以设置TTL key,比如每隔 30s 发送一次心跳使代表该机器存活的节点继续存在,否则节点消失。

这样就可以第一时间检测到各节点的健康状态,以完成集群的监控要求。

另外,使用分布式锁,可以完成 Leader 竞选。这种场景通常是一些长时间 CPU 计算或者使用 IO 操作的机器,只需要竞选出的 Leader 计算或处理一次,就可以把结果复制给其他的 Follower。从而避免重复劳动,节省计算资源。

参考:

etcd环境安装与使用的更多相关文章

  1. ETCD&Flannel安装

    .ETCD 安装: nohup etcd --name etcd0 \ --advertise-client-urls http://172.31.24.246:2379,http://127.0.0 ...

  2. 服务发现系统etcd之安装和使用

    一.概述 etcd是一个高可用的键值存储系统,主要用于共享配置和服务发现.etcd是由CoreOS开发并维护的,灵感来自于 ZooKeeper 和 Doozer,它使用Go语言编写,并通过Raft一致 ...

  3. ETCD 单机安装

    由于测试的需要,有时需要搭建一个单机版的etcd 环境,为了方便以后搭建查看,现在对单机部署进行记录. 一.部署单机etcd 下载 指定版本的etcd下载地址 ftp://ftp.pbone.net/ ...

  4. Kubernetes后台数据库etcd:安装部署etcd集群,数据备份与恢复

    目录 一.系统环境 二.前言 三.etcd数据库 3.1 概述 四.安装部署etcd单节点 4.1 环境介绍 4.2 配置节点的基本环境 4.3 安装部署etcd单节点 4.4 使用客户端访问etcd ...

  5. 使用专业的消息队列产品rabbitmq之centos7环境安装

      我们在项目开发的时候都不可避免的会有异步化的问题,比较好的解决方案就是使用消息队列,可供选择的队列产品也有很多,比如轻量级的redis, 当然还有重量级的专业产品rabbitmq,rabbitmq ...

  6. Linux下xampp集成环境安装配置方法 、部署bugfree及部署禅道

    XAMPP(Apache+MySQL+PHP+PERL)是一个功能强大的建站集成软件包.XAMPP 是一个易于安装且包含 MySQL.PHP 和 Perl 的 Apache 发行版.XAMPP 的确非 ...

  7. node.js环境安装,及连接mongodb测试

    1.node.js环境安装 npm config set python python2.7npm config set msvs_version 2013npm config set registry ...

  8. 谈谈React Native环境安装中我遇到的坑

    谈谈React Native环境安装 这个坑把我困了好久,真的是接近崩溃的边缘...整理出来分享给大家,希望遇到跟我一样问题的小伙伴能尽快找到答案. 首先,这是在初始化App之后,react-nati ...

  9. Kali Linux渗透测试实战 1.2 环境安装及初始化

    1.2 环境安装及初始化 目录(?)[-] 环境安装及初始化 下载映像 安装虚拟机 安装Kali Linux 安装中文输入法 安装VirtualBox增强工具 配置共享目录和剪贴板 运行 Metasp ...

随机推荐

  1. AJ学IOS 之ipad开发Popover的调色板应用_popover显示后其他控件仍然能进行交互

    AJ分享,必须精品 一:效果 后面的是xcode的控制台 二:代码 ViewController #import "ViewController.h" #import " ...

  2. Eclipse版本控制

    各版本的区别: 1.Eclipse IDE for Java Developers 是Eclipse的platform加上JDT插件,用来java开发的 2.Eclipse IDE for Java  ...

  3. Alpha Release Note 12/15/2015

    内容提要: ******Personal Photo Experience可供您存放所有的私人照片,系统会自动整理内容,您可以借助搜索功能快速找到所需图片,同时过滤重复图片和低质量图片,给您全新的搜索 ...

  4. Q - QQpet exploratory park HDU - 1493 (概率DP)

    题目大意: 一共有61个位置,标记为0~60.其中有10个重要位置,分别为:5, 12, 22, 29, 33, 38, 42, 46, 50 and 55. 有一个筛子,一共6个面,标有1~6.摇到 ...

  5. Java核心技术--接口与内部类

    接口implement 继承接口,即履行"义务". 接口中所有的方法自动属于public,在接口声明中,不必提供关键字public 接口中决不能含有实例域,也不能在接口中实现方法 ...

  6. 【LeetCode】57. Insert Interval [Interval 系列]

    LeetCode中,有很多关于一组interval的问题.大体可分为两类: 1.查看是否有区间重叠: 2.合并重叠区间;  3.插入新的区间: 4. 基于interval的其他问题 [ 做题通用的关键 ...

  7. gridview 合并单元格后,选中颜色重新绘制

    gv_docargo.RowStyle += OnRowStyle; private void OnRowStyle(object sender, DevExpress.XtraGrid.Views. ...

  8. webpack之Loader

    我们知道webpack的优点之一就是专注于处理模块化的项目,能做到开箱即用,但同时这也是webpack的缺点,只能用于模块化开发的项目,例如:Vue,React,Angular.Webpack在进行打 ...

  9. 十分钟搞懂Elasticsearch数字搜索原理

    更多精彩内容请看我的个人博客或者扫描二维码,关注微信公众号:佛西先森 前言 Elasticsearch诞生的本意是为了解决文本搜索太慢的问题,ES会默认将所有的输入内容当作字符串来理解,对于字段类型是 ...

  10. c++<ctime>中常用函数

    先说一下c++标准库并没有提供所谓的日期类型,而是继承了c的日期类型 <cmath>里面有些常用的函数,比如计时函数clock().获取系统时间的函数time(),下面就具体的介绍一下 1 ...