专栏首页公众号文章Botposter.com集群ETCD2.3.7升级至3.0实录

Botposter.com集群ETCD2.3.7升级至3.0实录

7月1日,ETCD隆重发布了3.0版本。Botposter.com也在第一时间对集群进行了升级。本文是升级过程的记录与总结(文中假设读者已经使用或测试过ETCD V2,如有不妥请见谅)。

Botposet.com是一款与HubSpot类似的营销自动化SAAS产品,全部使用golang开发。

说明

在Botposter.com中,ETCD主要用于以下两个职责:

  • master选举
  • 集群信息保存

早期曾使用ETCD的TTL来实现master心跳检测,由于性能原因在Botposter.com上个月的重构中取消了这种用法。这也恰好简化了升级难度,因为ETCD v3对TTL有重大改动。

准备

资料准备

迁移工作的主要参考以下两篇资料:

https://github.com/coreos/etcd/blob/master/Documentation/op-guide/v2-migration.md

https://github.com/coreos/etcd/blob/master/Documentation/upgrades/upgrade_3_0.md

测试环境

开始升级前需要搭建测试环境,过程非常简单,这一点ETCD做得非常好,V3版本与V2版本无论从安装方式和配置参数完全一致。

安装参考链接:https://github.com/coreos/etcd/releases

配置参考链接:https://github.com/coreos/etcd/blob/master/Documentation/op-guide/clustering.md

配置好测试环境后,使用etcdctl测试ETCD V3是否可以正常使用。这里需要注意,一定不要忘记在环境变量中加入ETCDCTL_API=3。否则在操作V3时,无论使用SET,GET都没有任何数据返回,也没有错误返回。建议ETCD V3可以提供错误提示。我在这里耽误了一些时间,因为想当然的以为,使用ETCD V3和ETCDCTL V3是默认匹配的。 ETCDCTL的文档链接:https://github.com/coreos/etcd/blob/master/etcdctl/README.md#migrate-options

注意:我在第一次使用etcdctl member list命令(所有的命令都会出错,此处以member list举例)的时候,返回下面错误代码:

grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp 127.0.0.1:22379: getsockopt: connection refused"; Reconnecting to {"127.0.0.1:22379" <nil>}

单独运行etcdctl命令,会返回etcdctl的使用帮助,其中有一行:

      --endpoints=[127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379]    gRPC endpoints

原来默认gRPC的endpoints有三个,解决这个问题的已知办法有两个: 一是在etcdctl命令行中加入--endpoints参数

etcdctl --endpoints=127.0.0.1:2379 member list

二是在etcd启动参数中增加其它端口

-listen-client-urls http://127.0.0.1:2379,http://127.0.0.1:22379,http://127.0.0.1:32379

在Botposter.com中暂时使用第二种方法。因为迁移时间有限,没有继续查看是否可以修改gRPC的默认--endpoints。

API V2与V3区别

  • 事务:ETCD V3提供了多键条件事务(multi-key conditional transactions),应用各种需要使用事务代替原来的Compare-And-Swap操作。
  • 平键空间(Flat key space):ETCD V3不再使用目录结构,只保留键。例如:"/a/b/c/"是一个键,而不是目录。V3中提供了前缀查询,来获取符合前缀条件的所有键值,这变向实现了V2中查询一个目录下所有子目录和节点的功能。
  • 简洁的响应:像DELETE这类操作成功后将不再返回操作前的值。如果希望获得删除前的值,可以使用事务,来实现一个原子操作,先获取键值,然后再删除。
  • 租约:租约代替了V2中的TTL实现,TTL绑定到一个租约上,键再附加到这个租约上。当TTL过期时,租约将被销毁,同时附加到这个租约上的键也被删除。

与Botposter.com有关的改动只有平键空间,因为系统中使用ETCD目录结构保存了master,node和task的全部信息。 从官方文档的表述看,事务和租约值得测试并用于优化V2的用法。

客户端代码升级

平键空间

将原代码中包含以下代码的部分都修改为

&client.GetOptions{Recursive: true}

都修改为

clientv3.WithPrefix()

数据类型

在V2版本中,resp.Node.ModifiedIndex的数据类型为uint64,V3中revision为int64。 因为在Botposter.com使用了resp.Node.ModifiedIndex作为全局序列标识,所以,需要将原系统中的数据类型修改为int64。

Compare-And-Swap

在V2的一种典型用法就是Compare-And-Swap,在Botposter.com中也使用这种方法实现了分布式锁,实现方法是在SET操作时增加下面的操作:

&client.SetOptions{PrevExist: "false"})

即,只有当前key不存在时,才能写入成功。

在V3中,改为由事务实现。具体代码如下:

kvc := clientv3.NewKV(&cli)r, _ := kvc.Txn(context.Background()).    If(clientv3.Compare(clientv3.CreateRevision(key), "=", 0)).    Then(clientv3.OpPut(key, v)).    Commit()

Txn的具体用法参考:https://godoc.org/github.com/coreos/etcd/clientv3#example-KV--Txn

Node

在V2中,get操作response回来的value保存在response.node.value,如果是一个directory,返回的结果集保存在response.node.nodes中。 V3做了大幅修改,因为V3中不再有directory,所有的key都是flat key,所以,所有get操作的返回值都保存在GetResponse.Kvs(数据类型是[]*mvccpb.KeyValue)中。而且V2中,keynotfound等错误在V3中都不再保留,V3中,当查询的key不存在时,GetResponse.Count为0,len(GetResponse.Kvs)也为0,Get操作返回的error为nil。 所以在V2中的代码如

response.Node.Value

需要改为

GetResponse.Kvs[0].Value

另外值得注意的是,V3中的key和value的返回值都是[]byte类型,这可以减少很多string与[]byte的数据类型转换操作。

ETCD升级

ETCD升级很简单,先按照安装参考链接:https://github.com/coreos/etcd/releases ,下载并解压文件。 因为Bostposter.com集群有自动恢复机制,所以使用离线升级的方式,在所有服务器运行脚本:

service etcd stopcp etcd /usr/local/binservice etcd start

ETCD的所有启动参数都不需要修改,升级时间不超过1秒。 ETCD升级后,升级集群服务的代码,只有在升级流程容器时需要重启2000多个流程,全部恢复时间大概在1分钟左右。

至此,升级工作全部完成。对系统功能和集群都做了测试,没有出现任何问题。

感受

下面说说升级到ETCD V3后的感受,时间有限没有做精确测试,没有数据支撑略显不够严谨。

首先,V3服务器端的内存比V2占用得更高,至少高50%。尤其是压力增大时,内存占用飙升得很快,压力减小后几分钟内存会释放出来。

其次,Client使用后一定要Close,因为在V2时,Botposter.com中使用了sync.pool来保存Client。当升级到V3后,操作频繁时池化的Client会占用非常多的内存,因为没有做具体测试,还不清楚一个Client占用多少内存。目前的解决办法是Client不再池化,而且使用后立即Close。

第三,V3的API更加合理,直接的结果是代码量减少了,异常处理也变得更简单。

第四,从升级后的整体表现看,V3的性能比V2要很多。

整体来说,在有条件的情况下,我建议升级至ETCD V3。时间仓促,如有笔误请大家及时指出,谢谢

本文分享自微信公众号 - 码农章为忠(coder-zwz),作者:Jesse_Joygenio

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2016-07-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Boot入门系列(十八)mybatis 使用注解实现增删改查,无需xml文件!

    之前介绍了Spring Boot 整合mybatis 使用xml配置的方式实现增删改查,还介绍了自定义mapper 实现复杂多表关联查询。虽然目前 mybati...

    架构师精进
  • Spring Boot入门系列(十一)如何整合Mybatis,实现增删改查【XML 配置版】

    今天主要讲解Springboot整合Mybatis,并实现最基本的增删改查功能。MyBatis 是现如今最流行的 ORM 框架之一,同时也支持普通的 SQL 查...

    架构师精进
  • Golang 入门系列(二)学习Go语言需要注意的坑

    上一章节我们已经了解了 Go 环境的配置,不了解的,请查看前面的文章 https://www.cnblogs.com/zhangweizhong/p/94599...

    架构师精进
  • 详解B+树及其正确打开方式

    前面我们知道了InnoDB数据页的7个组成部分,各个数据页组成了一个双向链表,而每个数据页中的记录按照主键从小到大的顺序组成一个单链表,每个数据页中为这些记录生...

    陈琛
  • 全球最大家谱网站Ancestry.com意外泄露了30万名用户的登录凭证

    “用指尖改变世界” ? Ancestry.com是全球最大的家谱网站和最大的家族历史在线社区,拥有海量的家谱数据库存贮量。用户可以通过Ancestry.com来...

    企鹅号小编
  • 王小河新入手一枚1816.com域名

    数字域名因其好记、高认知度的优点,所以能被用来广泛建站,也具有不错的市场价值!近日,又曝出投资人王小河收购了一枚四数字域名1816.com。

    躲在树上的域小名
  • [golang]Go net.lookup包

     DNS (Domain Name System 的缩写)的作用非常简单,就是根据域名查出IP地址。 域名系统(通常被称为“DNS”)是一个网络系统,允许我们把...

    landv
  • LeetCode 1472. 设计浏览器历史记录(双栈)

    你有一个只支持单个标签页的 浏览器 ,最开始你浏览的网页是 homepage ,你可以访问其他的网站 url ,也可以在浏览历史中后退 steps 步或前进 s...

    Michael阿明
  • 高效率工具

    btsync 是分布式网盘,里面可以存放任意内容,我就使用他来分享工具,本文的工具都提供btsync分享。如何安装参见这篇博客 因为百度分享经常失败,所以使用b...

    林德熙
  • 一些知名网站的 404 页面

    疯狂的技术宅

扫码关注云+社区

领取腾讯云代金券