我是靠谱客的博主 风趣酸奶,最近开发中收集的这篇文章主要介绍关于基于etcd服务的开发记录,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

以etcd作为持久化服务的开发与传统基于关系型数据库的开发有所区别,与基于Nosql数据库和redis的开发也不同,以下作记录:

  • etcd 主要用于非频繁更新的数据,如meta data等。 且提供订阅watchAPI, 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的更多介绍和原理见此, 其中这里将etcdZooKeeperConsul等作比较。这里也有一篇不错的中文参考。

  • etcd暴露的apiv2v3, 其区别见此, 推荐使用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-2etcd-3均状态正常,此时majority已设定为2, 但在一段时间后,etcd-3 节点故障, 失去通信,但其仍登记在集群, 只是状态为不可用。etcd-1etcd-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-3etcd-4quorum丢失。因此正确做法应该是先剔除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可以与远程或本地的etcdetcdctletcd的安装包内, 详见。使用举例如下:
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.例子运行机器是k8smaster节点。

  • etcd 几乎没有任何数据结构, 类似redis的set和 hashMap 等, 但一般使用时, 可以通过对key值的设计实现key之间的关联。如kubernetes中要获取所有namespaces, 其设计思路是将所有namespacekey/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作为存储层,实现各种ObjectCRUD操作, 涉及到一致性的例子是, 当多客户端在同一时刻对相同对象(相同namespace)进行更新等操作时, kubernetes的应对和实现逻辑。 从更新资源的Restful APIhandler实现, 源码见此, 到update 逻辑实现见此, 及此, 最后到持久化实现, 见此。可见k8s对于重要资源的更新,作了很多保证更新有效性的操作。

  • 相关议题:kubernetes 的namespace与etcd 3.2版本推出的namespace不是同一个概念。

Reference

https://yq.aliyun.com/articles/738055?spm=a2c4e.11155472.0.0.560075355p5Gc7

最后

以上就是风趣酸奶为你收集整理的关于基于etcd服务的开发记录的全部内容,希望文章能够帮你解决关于基于etcd服务的开发记录所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部