概述
以etcd作为持久化服务的开发与传统基于关系型数据库的开发有所区别,与基于Nosql数据库和redis的开发也不同,以下作记录:
-
etcd 主要用于非频繁更新的数据,如
meta data
等。 且提供订阅watch
的API
, redis也有类似功能 -
etcd
本质上是一个有序的k-v
存储,key
值用btree
存储在内存,value
存在磁盘。 -
etcd
采用raft算法作为一致性算法, 因此其瓶颈在于单个Leader
的问题,不能支撑较大的访问流量(QPS
)。分布式一致性问题是计算机科学的重要议题, 关于raft算法的基础原理见此 -
etcd
的性能benckmark
官方测试见此, 可见其在可接受的延时下(假定位50ms
)的, 合理客户端数(1 ~ 200 +
)下,其读写QPS
约在2000 - 16000
范围内。 -
由于
etcd
侧重于元数据的一致性存储及访问, 常用于服务发现或支撑元数据服务的存储层, 如其get
接口会返回除k-v
外的额外信息, e.g."revision":xxx
, 用于显示该k-v
被修改过的次数,在开发中, 可将其应用在业务逻辑中, kubernetes的典型例子见此, 其对etcd
的使用和理解是etcd
使用的最佳实践之一。 -
etcd
支持事务,每次事务完成只形成一次revision
, 关于etcd事务的详细描述见此, transaction本质上与redis 的pipeline不同,pipeling
内的命令不一定满足事务原子性。 -
关于
etcd
的更多介绍和原理见此, 其中这里将etcd
与ZooKeeper
和Consul
等作比较。这里也有一篇不错的中文参考。 -
etcd
暴露的api
有v2
和v3
, 其区别见此, 推荐使用v3 -
关于
etcd
的选举机制, 数据一致性机制和集群容错能力等的相关注意项, 如etcd
集群节点的增加注意点, 详见etcd FAQ 。文中有关于etcd
集群的节点数推荐为奇数的理由叙述,在这里概括一下:- 同一
etcd
集群内,数据一致性以大多数节点(majority
)为依据实施仲裁机制(quorum
),majority = (n/2)+1
。 如3节点的集群,majority
为2, 4节点的集群,majority
为3。若集群的majority
不能达到要求,则会失去仲裁quorum
, 引起数据丢失 。这一点容易引起误解, 这里以一个例子来阐述。如3节点集群在启动时,etcd-1
,etcd-2
和etcd-3
均状态正常,此时majority
已设定为2, 但在一段时间后,etcd-3
节点故障, 失去通信,但其仍登记在集群, 只是状态为不可用。etcd-1
和etcd-2
仍正常运作, 仍满足majority
为2的要求,quorum
正常。 若此后etcd-2
节点故障,则会导致不满足majority
为2的要求,quorum
丢失。 Failure Tolerance
为集群能容忍的最大故障节点数。Failure Tolerance = n - majroity
。承接上一点的例子, 可得奇数节点集群和偶数节点集群的Failure Tolerance
均为1。在Failure Tolerance
相同的情况下, 节点数越多,其故障的期望值越高。因此推荐奇数节点数集群。- 对于故障节点数已经达到
Failure Tolerance
的集群,直接增加新的etcd
节点的做法风险很高。举例,3节点集群, 故障节点为etcd-3
, 此时新增etcd-4
, 使得集群节点数变为4,majority
变为3。若此时etcd-4
配置错误, 则故障节点为etcd-3
和etcd-4
,quorum
丢失。因此正确做法应该是先剔除etcd-3
,再增加etcd-4
。 - 集群节点数越多,
Failure Tolerance
越高, 但节点间数据同步开销越大。虽然理论上etcd
集群节点数无限制,在最佳实践中推荐5个或7个节点。
- 同一
-
用
docker
搭建实验环境的etcd
很简单, 参见, 也可对docker-compose.yml
稍作修改, 使其暴露端口, 方便调试
version: '2'
services:
etcd:
image: bitnami/etcd:3
environment:
- ALLOW_NONE_AUTHENTICATION=yes
volumes:
- etcd_data:/bitnami
ports:
- "2379:2379"
- "2380:2380"
...
- 使用
etcdctl
可以与远程或本地的etcd
,etcdctl
在etcd
的安装包内, 详见。使用举例如下:
ETCDCTL_API=3 etcdctl --endpoints 127.0.0.1:2379 --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key get / --prefix --keys-only
以上etcdctl
列出kubernentes
中在etcd
中存储的所有key/value
.例子运行机器是k8s
的master
节点。
etcd
几乎没有任何数据结构, 类似redis
的set和 hashMap 等, 但一般使用时, 可以通过对key
值的设计实现key
之间的关联。如kubernetes
中要获取所有namespaces
, 其设计思路是将所有namespace
的key
以/foo/bar/..
的形式来表达集合包含关系, 如:
ETCDCTL_API=3 etcdctl ... get /registry/namespace --prefix --keys-only
/registry/namespaces/cattle-system
/registry/namespaces/default
/registry/namespaces/kube-node-lease
/registry/namespaces/kube-public
/registry/namespaces/kube-system
/registry/namespaces/label-system
/registry/namespaces/nginx-ingress
这里/registry/namespace --prefix
获取了所有以/registry/namespace
为前缀的key
。
-
key-value
中的value
一般为字节数组, 业务实现中可以对于重要的元数据, 在put
的时候用加密算法加密,get
用加密算法解密。 -
对删除和更新
key-value
等操作, 应符合事务操作规范, e.g. :
for {
txnResp, err := s.client.KV.Txn(ctx).If(
clientv3.Compare(clientv3.ModRevision(key), "=", origState.rev),
).Then(
clientv3.OpDelete(key),
).Else(
clientv3.OpGet(key),
).Commit()
if err != nil {
return err
}
if !txnResp.Succeeded {
getResp = (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange())
continue
}
return. ..
}
这里使用了事务和循环去确保所删除的对象为最后一次更新的对象。
-
相关议题:
kubernetes
使用etcd
作为存储层,实现各种Object
的CRUD
操作, 涉及到一致性的例子是, 当多客户端在同一时刻对相同对象(相同namespace
)进行更新等操作时,kubernetes
的应对和实现逻辑。 从更新资源的Restful API
的handler
实现, 源码见此, 到update 逻辑实现见此, 及此, 最后到持久化实现, 见此。可见k8s
对于重要资源的更新,作了很多保证更新有效性的操作。 -
相关议题:
kubernetes
的namespace与etcd 3.2
版本推出的namespace不是同一个概念。
Reference
https://yq.aliyun.com/articles/738055?spm=a2c4e.11155472.0.0.560075355p5Gc7
最后
以上就是风趣酸奶为你收集整理的关于基于etcd服务的开发记录的全部内容,希望文章能够帮你解决关于基于etcd服务的开发记录所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复