阅读 339

如何迁移数据到分布式文件系统

背景

前一阵子负责公司分布式文件技术选型、搭建集群、数据迁移等相关杂七杂八的工作,技术选型上一篇已经讲过了,这里重点聊聊集群和迁移。

搭建集群

集群是三台套路云机器,8C-16G-5M * 3

搭建 Minio 的负载均衡集群,官方推荐无外乎两种方式: Docker Swarm 与 Kubernetes (K8S「K-S共8个字母因此得名」) 两种方式,K8S 不是我负责,所以我先使用 Swarm 来搭建集群先保证测试通过即可。

集群搭建方式也很简单,直接看官网的例子: https://docs.min.io/docs/deploy-minio-on-docker-swarm

稍微用过一点 docker 的人看一下就可以,稍微注意一点:记住集群的 Leader 的编号、后面迁移也会用到。

多租户的方式

初步打算负载四个不同的环境

既然用了集群,就需要考虑多租户的问题了,Minio 的桶最初的设想我是想单租户用来放 COMPANYID 的,这个思想有点类似 ElasticSearch 中的 _routing,这样可以海量数据均匀分布,以后的横向扩容、数据迁移都十分的方便。但是考虑到这样一来就没有机器给 「测试机器」「金丝雀机器」「研发本地开发」「备用机」搭建环境了,确实有点浪费,所以经过深思熟虑改变策略:

以域名作为桶区分租户,以前硬盘的数据原路写到 Minio,换句话说一个环境一个桶,这样目前好处也很明显:

  • 省机器
  • 迁移更简单了,因为不用考虑 routing 的问题
  • 省时间,我们有更多喘息的时间去优化业务,而不用再去压榨时间

迁移到文件系统

刚好前几天看了本书《分布式服务架构 原理、设计与实战》,本来挺好奇的,读一读发现挺水的,不如叫 《近两年常见的分布式架构介绍》,不过速度一番也能看到一些有用的东西。作者写了这么一句:

平滑系统迁移四个阶段:

  • 在新老系统上双写
  • 迁移双写之前的老数据到新系统
  • 读取新系统数据数据
  • 将新数据写到新系统

但是我个人感觉,双写后较难马上发现问题,马上修复,所以双写并没有大规模的实践,因为我也不确定,双写后本地 IO 关掉会发生多少问题。


迁移的工作是最复杂最容易遗漏的、需要我们留心观察,尽量一步到位,与测试人员沟通细心测试所有相关文件内容,避免以后的麻烦

要调整哪里?

系统资源全部改为文件系统集群,说白了就是「上云了」,所有服务器本地 IO 都绝对不能再有。否则负载均衡时会出现 A B C 三台机器轮询,66.6%的几率访问不到资源的 BUG,为以后研发人员的调试,和测试同事找麻烦。所以这里要尽量找到所有的:

上传的调整

  • 所有系统 IO 级别的操作代码

比如 outputSream read write flush 等关键参数全局搜一搜,需要下一步改为以流的方式传到分布式文件系统中。

  • 所有微服务都要同步调整

其中有些通用上传的改下能解决 50% 的问题,剩余的就五花八门了,有定时 Task 写到 openResty 静态资源目录的,有写到系统 /mnt/xxx 下的,刚好趁机与领导碰一下,制定一套规则,涉及到 N 个微服务 + 一些报表服务 + 一些中间件微服务『压缩服务、文件预览服务』 等,共同调整。

软规则,口头 + 文档说明,并非在代码指定好 Utiil + Contacts 的硬性规则,因为微服务众多,短期内只能做点妥协。

读取的调整

上面的只是上传的一些问题,下面说说读取的问题

代理问题

之前用的是 openResty 的静态目录,现在迁移到文件系统自然需要前端平滑的过滤到 Minio 上,前端不能有太大的改动,前后端一起调整是灾难性的,我很忌讳这样的操作。

打个比方原来前端:

  • ounter(line
/checkJpg/routing/xxx/user/xxx/xx.jpg复制代码

迁移到 Minio 后

  • ounter(line
/minio_host/checkJpg/routing/xxx/user/xxx/xx.jpg复制代码

注意:minio 桶禁止大写字母

我们不可能让前端加个 Base_Url 因为很多都是后端早早持久化到 Mysql 或者 ES 中了,前端对此肯定无能为力。所以使用 openResty rewrite 重写了路由,当然安装 lua 插件也可以。

比如这样:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
location ~^/checkJpg {复制代码	   proxy_buffering off;复制代码	   rewrite ^//checkJpg/(.*)$ /minio_host/checkJpg/$1;复制代码	   proxy_set_header Host $http_host;复制代码	   # 然后代理 checkjpg 到 minio 集群: 复制代码	 }复制代码
复制代码

权限问题

其实开始我考虑到了 Minio 的令牌权限问题,代理时设为公开来桶的安全问题,要不要写个 lua 脚本做验证,后来发现自己特傻想多了,可能想多了,参考 行业 BAT Github 等众多服务,也没见谁把 OSS 搞成验证的,所以这样应该可以,若以后有需求涉及到用户敏感信息预防万一的话,分分钟加个验证不是问题。

还有本地一些 IO 读取操作,与上文的上传同理,按部就班的修改就可以了。

接下来 merge 代码之后,扔到一个分支上,然后进行老数据的迁移工作。

迁移

迁移呢,我选择的 Minio 官方的 mc 客户端,操作简单容易上手,我也自己简单整理了一下:

由于先临时测试 我先临时 docker 搭建了单台 Minio 进行测试,待测试全部通过,发布集群。

安装 s3cmd

  • ounter(line
    yum install s3cmd  # centos、具体看 https://s3tools.org/repositories复制代码

安装 minio

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line

复制代码
# linux/macos 复制代码 wget https://dl.min.io/server/minio/release/linux-amd64/minio复制代码 chmod +x minio复制代码 ./minio server /data复制代码

先启动一下看看 私钥 然后 nohup

nohup ./minio server /data &
复制代码
mdfQgS.png
mdfQgS.png

安装 mc

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
 # linux/macos   /home/minio/复制代码 wget https://dl.minio.io/client/mc/release/linux-amd64/mc复制代码 chmod +x mc复制代码 ./mc --help复制代码

mc 添加 minio 地址

  • ounter(line
  • ounter(line
    # mc config host add <alias> <ip:port> <access key> <> <aws相关版本 s3v4即可>复制代码    mc config host add qmenhu http://localhost:9000  4NMXJ94DEJHKTSI42B9D  Kwbypq+4sySAqWl7AN0kSfZT5jLJfTq96B3CdMIO  S3v4复制代码

创建需要的桶

  • ounter(line
  • ounter(line
  • ounter(line
    mc mb qmenhu/checkjpg 复制代码    # 所有的大写都是不允许的 具体:https://github.com/minio/minio/pull/5095#discussion_r147351020复制代码    # 其实也可以代理回来大写的 :9000/minio/checkJpg复制代码
mdfM38.png
mdfM38.png

设为公开 (无秘钥访问) 公开的桶,无需秘钥访问、可以硬盘写入资源「硬盘写入能否同步未测」

  • ounter(line
    mc policy public qmenhu/checkjpg复制代码

Access permission for qmenhu/checkjpg is set to public

开始迁移数据

先配置下

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line

复制代码
vim ~/.s3cfg复制代码
复制代码
# 设置endpoint复制代码host_base = 127.0.0.1:9000复制代码host_bucket = 127.0.0.1:9000复制代码bucket_location = us-east-1复制代码use_https = False #如果升级了 https 就放开复制代码 复制代码# 设置access key和secret key,「启动时的,一般不会变」复制代码access_key = 4NMXJ94DEJHKTSI42B9D复制代码secret_key = Kwbypq+4sySAqWl7AN0kSfZT5jLJfTq96B3CdMIO复制代码 复制代码# 启用S3 v4版本签名API复制代码signature_v2 = False复制代码
复制代码

执行迁移命令

  • ounter(line
  • ounter(line
  • ounter(line
    s3cmd sync /usr/local/nginx/html/checkJpg/ s3://checkjpg  #从 本地 到 minio复制代码    复制代码    #s3cmd sync s3://checkjpg /usr/local/nginx/html/checkJpg/  从 minio 到 本地复制代码

主要取决于文件个数+磁盘速度「14888图片| 1224Mb | 719s」

mdfFje.png
mdfFje.png

minio

迁移完成的检查

完成之后,删掉 Linux 服务器本地原有的资源,gitLab-runner 部署刚才 checkout 的大家调整的分支,交给测试的同事测试。

结果还可以,测试的同学们1个小时给我们提了 20+ 个 BUG,不过都轻轻松的改完了,之后的陆陆续续的小问题也很快就迎刃而解了。那么单台测试效果很理想,只需要迁移到集群就OK了

迁移数据到集群

后面的重复工作我就不做了,交给运维来做,说明关键点,注意尽量往 Swarm 指定的 Leader 机器来写数据,方便「从」机器同步数据。

集群迁移总结

  • 修改写

  • 修改读

  • 检查各个需要调整的服务

  • 单台迁移数据测试「金丝雀」

  • 测试集群

  • 发布

不仅是文件系统,通过这次的迁移冒险,以后迁移任何集群都可以借鉴。此文非技术性文章,纯属分享经验。

首发地址 :github.com/pkwenda/Blo…