官方地址 https://etcd.io
Github官方地址:https://github.com/etcd-io/etcd
中文文档:https://doczhcn.gitbook.io/etcd/index/index/interacting_v3
etcd应用场景
服务发现
服务发现要解决的也是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务,要如何才能找到对方并建立连接。本质上来说,服务发现就是想要了解集群中是否有进程在监听 udp 或 tcp 端口,并且通过名字就可以查找和连接。
配置中心
将一些配置信息放到 etcd 上进行集中管理。
这类场景的使用方式通常是这样:应用在启动的时候主动从 etcd 获取一次配置信息,同时,在 etcd 节点上注册一个 Watcher 并等待,以后每次配置有更新的时候,etcd 都会实时通知订阅者,以此达到获取最新配置信息的目的。
分布式锁
因为 etcd 使用 Raft 算法保持了数据的强一致性,某次操作存储到集群中的值必然是全局一致的,所以很容易实现分布式锁。锁服务有两种使用方式,一是保持独占,二是控制时序。
- 保持独占即所有获取锁的用户最终只有一个可以得到。etcd 为此提供了一套实现分布式锁原子操作 CAS(
CompareAndSwap
)的 API。通过设置prevExist
值,可以保证在多个节点同时去创建某个目录时,只有一个成功。而创建成功的用户就可以认为是获得了锁。 - 控制时序,即所有想要获得锁的用户都会被安排执行,但是获得锁的顺序也是全局唯一的,同时决定了执行顺序。etcd 为此也提供了一套 API(自动创建有序键),对一个目录建值时指定为
POST
动作,这样 etcd 会自动在目录下生成一个当前最大的值为键,存储这个新的值(客户端编号)。同时还可以使用 API 按顺序列出所有当前目录下的键值。此时这些键的值就是客户端的时序,而这些键中存储的值可以是代表客户端的编号。
安装
源码安装
下载地址https://github.com/etcd-io/etcd/releases
cd /opt/sofaware/
wget https://github.com/etcd-io/etcd/releases/download/v3.4.0/etcd-v3.4.0-linux-amd64.tar.gz
解压文件
# mkdir -p /opt/module
# tar -zxf etcd-v3.4.0-linux-amd64.tar.gz -C /opt/module/
# cd /opt/module/
# mv etcd-v3.4.0-linux-amd64/ etcd
查看当前目录结构
# ls -ll
total 40296
drwxr-xr-x 14 1922357897 wheel 4096 Sep 16 23:46 Documentation
-rwxr-xr-x 1 1922357897 wheel 23667040 Aug 30 23:54 etcd
-rwxr-xr-x 1 1922357897 wheel 17513984 Aug 30 23:54 etcdctl
-rw-r--r-- 1 1922357897 wheel 43094 Aug 30 23:54 README-etcdctl.md
-rw-r--r-- 1 1922357897 wheel 8431 Aug 30 23:54 README.md
-rw-r--r-- 1 1922357897 wheel 7855 Aug 30 23:54 READMEv2-etcdctl.md
配置环境变量
vim /etc/profile
export PATH=$PATH:/opt/module/etcd
切记一定要执行
source /etc/profile
查看安装版本信息
# etcd --version
etcd Version: 3.4.0
Git SHA: 898bd1351
Go Version: go1.12.9
Go OS/Arch: linux/amd64
MacOS安装
建议使用brew 安装
# brew install etcd
To have launchd start etcd now and restart at login:
brew services start etcd
Or, if you don't want/need a background service you can just run:
etcd
docker-compose安装
docker-compose.yaml 文件如下
version: '2'
networks:
etcd-net:
services:
etcd1:
image: quay.io/coreos/etcd:v3.3.18
container_name: etcd1
command: etcd -name etcd1 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- etcd-net
etcd2:
image: quay.io/coreos/etcd:v3.3.18
container_name: etcd2
command: etcd -name etcd2 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- etcd-net
etcd3:
image: quay.io/coreos/etcd:v3.3.18
container_name: etcd3
command: etcd -name etcd3 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
ports:
- 2379
- 2380
networks:
- etcd-net
启动
$ docker-compose up
验证
sudo docker exec -t etcd1 etcdctl member list
ade526d28b1f92f7: name=etcd1 peerURLs=http://etcd1:2380 clientURLs=http://0.0.0.0:2379 isLeader=false
bd388e7810915853: name=etcd3 peerURLs=http://etcd3:2380 clientURLs=http://0.0.0.0:2379 isLeader=false
d282ac2ce600c1ce: name=etcd2 peerURLs=http://etcd2:2380 clientURLs=http://0.0.0.0:2379 isLeader=true
配置参数
--name:方便理解的节点名称,默认为default,在集群中应该保持唯一,可以使用 hostname
--data-dir:服务运行数据保存的路径,默认为 ${name}.etcd
--snapshot-count:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘
--heartbeat-interval:leader 多久发送一次心跳到 followers。默认值是 100ms
--eletion-timeout:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms
--listen-peer-urls:和同伴通信的地址,比如 http://ip:2380,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost!
--listen-client-urls:对外提供服务的地址:比如 http://ip:2379,http://127.0.0.1:2379,客户端会连接到这里和 etcd 交互
--advertise-client-urls:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
--initial-advertise-peer-urls:该节点同伴监听地址,这个值会告诉集群中其他节点
--initial-cluster:集群中所有节点的信息,格式为 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:这里的 node1 是节点的 --name 指定的名字;后面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值
--initial-cluster-state:新建集群的时候,这个值为new;假如已经存在的集群,这个值为 existing
--initial-cluster-token:创建集群的token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误
所有以--init开头的配置都是在bootstrap集群的时候才会用到,后续节点的重启会被忽略
创建etcd 数据目录
# mkdir -p /data/etcd #建议创建单独的etcd数据目录
启动项配置
vim /etc/systemd/system/etcd.service
[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target
[Service]
User=root
Type=notify
EnvironmentFile=-/opt/module/etcd/config/etcd.conf
ExecStart=/opt/module/etcd/etcd
Restart=on-failure
RestartSec=10s
LimitNOFILE=40000
[Install]
WantedBy=multi-user.target
配置信息
mkdir -p /opt/module/etcd/config/
cd /opt/module/etcd/config/
vim etcd.conf
ETCD_NAME=etcd3
ETCD_DATA_DIR="/data/etcd"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://http://123.456.769.190:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://http://123.456.769.192:2380,etcd2=http://http://123.456.769.191:2380,etcd3=http://http://123.456.769.190:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://123.456.769.190:2379"
name:本member的名称;
data-dir:存储的数据目录;
listen-client-urls:用于监听客户端etcdctl或者curl连接;0.0.0.0表示监听本机所有地址;
listen-peer-urls:用于监听集群中其它member的连接;0.0.0.0表示监听本机所有地址;
advertise-client-urls: 本机地址, 用于通知客户端,客户端通过此IPs与集群通信;
initial-advertise-peer-urls:本机地址,用于通知集群member,与member通信;
initial-cluster:描述集群中所有节点的信息,描述每个节点名称、ip、端口,集群静态启动使用,本member根据此信息去联系其他member;
initial-cluster-token:集群唯一标示;
initial-cluster-state:集群状态,新建集群时候设置为new,若是想加入某个已经存在的集群设置为existing
启动etcd
启动的 etcd 成员在 localhost:2379
监听客户端请求。
systemctl daemon-reload && systemctl enable etcd && systemctl start etcd
基本操作
docker进入etcd实例
$ docker exec -it etcd_node1_1 /bin/sh
通过使用 etcdctl 来和已经启动的集群交互:
# 使用 API 版本 3
$ export ETCDCTL_API=3
$ ./etcdctl put foo bar
OK
$ ./etcdctl get foo
bar
插入数据
#etcdctl put key1 value1
OK
获取数据
# etcdctl get key1
key1
value1
获取前缀的数据
# etcdctl get key --prefix
key1
value1
删除数据
# etcdctl del key1
1
# etcdctl del key
0
观察数据变化
etcdctl put key2 value2
etcdctl put key2 value22
# etcdctl watch key2
PUT
key2
value2
PUT
key2
value22
列出成员
etcdctl member list
检查集群状健康状态
etcdctl endpoint health
参考
https://github.com/etcd-io/etcd/releases
https://etcd.io/docs/v3.4.0/demo/
https://www.cnblogs.com/51wansheng/p/10234036.html
https://www.jianshu.com/p/44022c67f117
https://www.infoq.cn/article/etcd-interpretation-application-scenario-implement-principle
https://gitbook.cn/books/5bb037728f7d8b7e900ff2d7/index.html