## 安装
下载地址:https://github.com/etcd-io/etcd/releases
下载完成解压后,目录中有两个二进制文件, etcd以及 etcdctl。其中 etcd就是运行etcd服务的二进制文件, etcdctl是官方提供的命令行etcd客户端,使用 etcdctl可以在命令行中访问etcd服务。
查看etcd版本 `./etcd --version`
## 运行
### 单点启动
查看启动帮助 `./etcd -h`
启动 `./etcd`
```
2019-11-01 10:04:11.922204 I | embed: name = default
2019-11-01 10:04:11.922204 I | embed: data dir = default.etcd
2019-11-01 10:04:11.922204 I | embed: member dir = default.etcd\member
2019-11-01 10:04:11.922204 I | embed: heartbeat = 100ms
2019-11-01 10:04:11.922204 I | embed: election = 1000ms
2019-11-01 10:04:11.922204 I | embed: snapshot count = 100000
2019-11-01 10:04:11.923204 I | embed: advertise client URLs = http://localhost:2379
2019-11-01 10:04:11.923204 I | embed: initial advertise peer URLs = http://localhost:2380
2019-11-01 10:04:11.923204 I | embed: initial cluster =
```
etcd服务启动后提供给外部客户端通信的端口是2379,而etcd服务中成员间的通信端口是2380(Peer是对同一个 etcd 集群中另外一个 Member 的称呼).
`-name `节点名称,默认是UUID
`-data-dir` 保存日志和快照的目录,默认为当前工作目录
`-addr` 公布的ip地址和端口。默认为`127.0.0.1:2379 `
`-bind-addr` 用于客户端连接的监听地址,默认为-addr配置
`-peers` 集群成员逗号分隔的列表,例如 `127.0.0.1:2380,127.0.0.1:2381 `
`-peer-addr` 集群服务通讯的公布的IP地址,默认为 `127.0.0.1:2380`.
`-peer-bind-addr` 集群服务通讯的监听地址,默认为-peer-addr配置
`--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,这个值每个集群保持唯一。
### 集群启动
在安装和启动 etcd 服务的时候,各个节点需要知道集群中其他节点的信息(一般是 ip 和 port 信息)。根据你是否可以提前知道每个节点的 ip,有几种不同的启动方案:
1. 静态配置:在启动 etcd server 的时候,通过 `--initial-cluster` 参数配置好所有的节点信息
2. 使用已有的 etcd cluster 来注册和启动,比如官方提供的 discovery.etcd.io
3. 使用 DNS 启动
## 基础知识
每个 etcd cluster 都是有若干个 member 组成的,每个 member 是一个独立运行的 etcd 实例,单台机器上可以运行多个 member。
在正常运行的状态下,集群中会有一个 leader,其余的 member 都是 followers。leader 向 followers 同步日志,保证数据在各个 member 都有副本。leader 还会定时向所有的 member 发送心跳报文,如果在规定的时间里 follower 没有收到心跳,就会重新进行选举。
客户端所有的请求都会先发送给 leader,leader 向所有的 followers 同步日志,等收到超过半数的确认后就把该日志存储到磁盘,并返回响应客户端。
每个 etcd 服务有三大主要部分组成:raft 实现、WAL 日志存储、数据的存储和索引。WAL 会在本地磁盘(就是之前提到的 --data-dir)上存储日志内容(wal file)和快照(snapshot)。
## etcdctl命令
### API版本设置
使用etcd v3
`export ETCDCTL_API=3` `set ETCDCTL_API=3`
查询集群成员
`./etcdctl member list`
查询节点状态
` ./etcdctl --endpoints localhost:2379 endpoint status --write-out="table"`
### 监听一个key
`./etcdctl watch /key/test`
### 增删改查key
```
./etcdctl put /key/test 11
OK
./etcdctl get /key/test
/key/test
11
./etcdctl put /key/test 22
OK
./etcdctl get /key/test
./etcdctl get /key/test
/key/test
22
etcdctl del /key/test
1
#删除所有/key 前缀的节点
etcdctl del /key --prefix
```
### 租约
申请租约,从申请开始计算时间
```
λ ./ettcdctl lease grant 30
lease 694d6e1b7f77f40b granted with TTL(30s)
```
授权租约,节点的生命伴随着租约到期将会被DELETE
```
λ ./etcdctl put --lease=694d6e1b7f77f40b /key/leasetest "leasetest"
OK
```
撤销租约,撤销租约和租约到期一样,节点都会被删除
```
./etcdctl lease revoke 4e5e5b853f5286cc
lease 4e5e5b853f5286cc revoked
```
租约续约,每当到期将会续约
```
./etcdctl lease keep-alive 4e5e5b853f52892b
lease 694d6e1b7f77f40b keepalived with TTL(40)
lease 694d6e1b7f77f40b keepalived with TTL(40)
```
## 核心API
### KV:键值相关操作
对外提供的接口:
```
type KV interface {
// 存放.
Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)
// 获取.
Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)
// 删除.
Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)
// 压缩rev指定版本之前的历史数据.
Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error)
// 通用的操作执行命令,可用于操作集合的遍历。Put/Get/Delete也是基于Do.
Do(ctx context.Context, op Op) (OpResponse, error)
// 创建一个事务,只支持If/Then/Else/Commit操作.
Txn(ctx context.Context) Txn
}
```
### Watch:观察者模式,监听数据变化
对外提供的接口:
```
type Watcher interface {
// 监视key的变化,返回变化的结果
Watch(ctx context.Context, key string, opts ...OpOption) WatchChan
// 关闭所有监视器
Close() error
}
```
### Lease:租约相关操作
对外提供的接口:
```
type Lease interface {
// 分配一个租约.
Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, error)
// 释放一个租约.
Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error)
// 获取剩余TTL时间.
TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error)
// 获取所有租约.
Leases(ctx context.Context) (*LeaseLeasesResponse, error)
// 续约保持激活状态.
KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error)
// 仅续约激活一次.
KeepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAliveResponse, error)
// 关闭续约激活的功能.
Close() error
}
```
### Cluster:集群管理相关操作
对外提供的接口:
```
type Cluster interface {
// 列出集群所有成员.
MemberList(ctx context.Context) (*MemberListResponse, error)
// 添加新成员到集群中.
MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error)
// 移除一个集群中的成员.
MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error)
// 更新一个集群成员的地址.
MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error)
}
```
有疑问加站长微信联系(非本文作者))