总结一次 Pika 迁移遇到的坑

image

目录:

  1. 背景
  2. 方案
  3. 迁移步骤详细
  4. 坑点统计
  5. 总结

前言

这段时间一直在弄数据迁移,需要把阿里云经典网络的中间件等基础设施迁移到 VPC 网络,包括 Pika,代理 Pika 的 Codis,zookeeper ,Sentinel 等。

其中,pika 的坑是最多的(大概是用户少的原因?)。这里简单的把迁移方案,再到迁移过程遇到的坑总结一下,方便后人,也方便回溯。

1 背景

整件事情的大背景就是公司要把所有的服务从阿里云经典网络迁移到 VPC 网络,包括 KV 存储。当然还有其他的,例如文件服务,配置中心,发布平台等基础服务。笔者负责的则是配置中心和 Pika 迁移。同时,迁移过程要是平滑的,不能影响业务。这里主要讲讲 Pika 的迁移。(实际上,涉及到存储的在线迁移都是十分麻烦的)

2 方案

开始的时候,我们设计了 2 个方案。

  1. 通过在新的网络环境增加 Pika 节点,使用 Codis 将老环境的数据迁移到新 Pika 中,同时,在新环境中增加 Codis 节点,也就是让 2 个 Codis 集群双写一个 Pika 实例,实现数据同步。

优点:没有方案 二 的缺点。。。。
缺点: Codis 双写单实例 Piak, 理论上可以,但没有人这么做过,有风险。同时,老环境需要跨网络访问新环境 Pika,增减机器都需要配置 classLink —— 麻烦。

  1. 使用 Pika 的双主功能,新旧环境各有一个 Pika 实例,搭建成双主模式(数据一致性问题在业务接受范围内),完成数据同步。

优点:没有方案一 的缺点。。。
缺点:Pika 双主方案不成熟,需要长期保持双主同步(稳定性问题),有一定的数据一致性问题。

最终,我们在测试了 Pika 的双写功能后,同时和业务沟通了双主同步的时间(时间不是很长)和对数据一致性的容忍度,选择了方案 2。

同时,我们还有 2 个问题:

第一,我们线上的版本是 2.3.0,这个版本有个 bug,我们希望升级一下,但是不能升级到 3.0.0(含) 以上版本(不支持 codis ,pika-hub, geo 相关 API ,不过貌似有分支版本支持 Codis, 但需要到群里 @首席编外客服)。

第二,双主功能需要修改配置文件,且需要重启,但是业务要求不能重启。有 2 种办法:

  1. 利用主从同步功能,新增从节点,在从节点添加双主配置,全同步主节点数据,然后手动故障转移从节点,完成双主配置修改。
    但是:注意!pika 的 2.3.3 以上版本是不兼容以下版本的主从同步的! 也就是说,如果想升级到 2.3.3 版本解决这个 bug,那么,就不能利用在线主从同步的功能,只能重启! 所以这个方案我们放弃了

  2. 利用 codis 的迁移 slot 的功能,将旧版本节点数据迁移到新节点。完成在线迁移。

所以,当然是选择第二个办法。

3 迁移步骤详细

迁移步骤:

  1. 在经典网络新建一个 2.3.6 版本 pika 实例,准备好双主配置(server-id,master-ip,port)。
  2. 使用 codis 的 migrate some 功能,将老 pika 节点的数据迁移到新 pika 节点。
  3. 在 VPC 网络新建一台 pika 实例,和步骤 1 的 pika 实例组成双主,并执行双主同步。
  4. 在 VPC 网络搭建 zk 集群,codis 代理等中间件。方便 VPC 环境的客户端访问。从而完成迁移。

迁移过程动图

4 坑点统计

  1. Pika 2.3.3版本添加了主从Server ID认证机制,无法之前的所有版本无法建立主从关系,升级请注意! 如果线上的是 2.3.3 版本一下,是无法建立主从关系的(这个感觉坑的有点严重)。

  2. pika3.0暂不支持codis,pika-hub,geo相关api。如果非要支持,可以使用分支代码。找首席编外客服。

  3. 3.0.0 之前有个 bug,主库 rsync 失败可能无法再次 rsync 直到重启,这个需要注意。

  4. 双主模式有很多状态(repl_state):双方都是 3 表示成功,如果主动复制节点状态是 0,则需要执行 slaveof 进行全同步,执行命令后,通常,被同步节点状态是 0,warning 日志显示发送文件中。主动复制节点状态状态此时通常为 4,表示正在接收对方 rsync 发送的数据,此时等待即可,同时日志显示正在 from master after trysync wait。当 rsync 全同步结束后,双方状态变为 3.

  1. 如果 slaveof 失败,观察同步双方的 warning 日志,如果显示 rsync send file failed,可能是你的机器上没有安装 rsync。安装后便可支持同步。(这个是我花时间比较多的地方,由于日志不够明确,导致根本没有关注 rsync 是否安装这个事情,一直认为问题在网卡那里,导致耗时很久,过生日那天还在加班。。。)

  2. 注意 rsync 端口不要被占用,rsync 端口为: pika 端口号 + 3000,例如:pika 端口号为 9221,那么 rsync 端口号就是 12221.( + 1000 是 binlog 接收端口, + 2000 是心跳端口,记得打开)。

  3. 如果还是同步失败,可能是网卡问题,通常默认路由是外网(如果你有 2 张网卡,可使用 ifconfig 查看),需要在 Pika.conf 配置文件中指定网卡,官方建议绑定内网网卡。外网网卡在 2.3.6 版本会有问题。

  4. 如果同步失败,想重新同步,记得删除主动同步方的 log/ 目录。

  5. pika 会对数据进行压缩,大概平均 3-5 倍,所以,你看到的数据量和你写入的数据量会不太一样,不用担心。pika 的 info keyspace 命令结果不是实时的,需要使用 info keyspace 1 异步扫描 key,等待一会,就可以看到 key 的数量。

  6. pika 的 slave read only 有可能失效,导致双写失败。需要使用 Config set slave-read-only no 修改一下。

  7. 如果想让 Codis(3.2) 迁移 pika ,那么需要修改 Codis 的dashboard.toml 配置文件为 migration_method = "sync", 否则会报错。网上有文章说 3.0 支持 “semi-aync”(号称速度是 3000key / s ),但是我这边 3.2 版本不行,必须要修改成 sync。迁移速度在 300key / s 左右。同时,需要打开 Pika.conf配置文件中slotmigrate : yes开关。
    相关 issue:
    1. pika加入到codis3.0报错
    2. coids3.2使用pika做后端出现错误
    3. Migrate的性能是不是很慢,8cpu 64G内存,迁移的速度是500key/s

  1. 建议使用 SSD,否则会非常慢(但感觉使用 Pika 的大部分同学都是为了省钱,估计用所谓的高效云盘的会比较多)。

以上是 Pika 需要注意的地方,建议在使用的时候,多看看每个版本的 Release Log,

另外,由于我是第一次接触 Codis,因此记录一下第一次使用 Codis 遇到的坑:

  1. Codis 的安装最好使用编译安装,二进制安装,貌似不能修改配置文件。编译的时候目录一定要和 github 上的文档一致。make 的时候,可能会出现错误,按照提示安装一个工具就好了。

  2. dashboard.toml 配置文件中的 admin_addr 选项配置的是 0.0.0.0 网卡,建议换成 ip 地址,否则,proxy 会把机器 host 名字注册到 zk,客户度从 zk 拿到的是 host 名字,而不是 ip,除非你蛋疼的需要修改 host 文件。

  3. 在 proxy 配置文件中, jodis 的相关配置,就是 zk/etcd 的配置,例如,jodis_name 就是 “zookeeper”,jodis_addr 就是 “ip:2181”。这个其实就是把这个 proxy 注册到指定的注册中心里。方便客户端从注册中心拿到 proxy。

  4. jodis 的使用:proxy 配置文件里做了 proxy 注册时的路径说明,2.0 版本的路径较长,我们使用的是 3.0 版本,路径是 /jodis//jodis/{PRODUCT_NAME}/proxy-{HASHID}。在使用 Jodis 客户端的时候,不必指定 hashId。

客户端代码如下:

JedisResourcePool jedisPool = RoundRobinJedisPool.create()
.curatorClient("xx.xx.xx.xx:2181", 30000)
.zkProxyDir("/jodis/xx-codis-xx")
.build();

Jedis jedis = jedisPool.getResource();
jedis.set("foo", "hello");
String value = jedis.get("foo");
System.out.println(value);

jedis.close();

5 总结

零零散散说了很多,都是这两天遇到的坑,但基本总算迁移成功了,还剩下 Sentinel 没有搭建,但问题不大。

在整个迁移过程中,最大的感悟就是使用一个开源中间件真的有很多的坑要踩,幸好 pika 有个技术支持群,虽然网上文章不多,但技术支持群还算可以的。提问都能够很好的解答,这点赞一个。但不可否认,坑确实还挺多,特别是哪个高版本不支持低版本主从同步的问题,很蛋疼 —— 如果没有 Codis 的迁移功能,真的很麻烦,甚至要重启。

然后,换个角度想,如果你要做一个开源中间件,要想做好他,就需要有个好的生态,即:能够及时解答用户问题,快速解决 bug,用户也会有很多的内容输出帮助到其他人,例如在第一次使用 Codis 的时候,网上经验就很多,有些坑就不必踩,即使踩到了,也能很快搜索到解决办法。另外,在兼容第三方中间件的时候,也能够较好的支持,例如,如果 Pika 3.0 能较好的支持 Codis,那体验一定好很多,对 Pika 的开源发展也会好很多。

还有一个感触做软件的时候,日志一定要尽量明确,Pika 在全量同步时,依赖 rsync,如果用户没有安装 rsync ,Pika 的提示只是简单的提示 fail,事实上,这里的 Log 可以更详细些,当然我也提了建议,Pika 的开发人员表示后期会优化一下提示。(这个问题差点让我们放弃双主同步的方案)

好了,这个就是这次踩坑的经验之谈,如有不当,敬请指出!

结尾放一张踩坑图