一、产品考察
根据上一次存储块环境建设的三个月时间后,接到了阿里云产品线的通知,共享存储块开始商业化,以每GB/月的单位计费,价格不菲,但数据昂贵,要赶在商业化之前将数据挪走,我们想到了阿里云的成熟产品,OSS对象存储(ObjectStorge Service)。使用oss有出色优势让企业级管理数据得到了安心。
可靠性,受限于硬件可靠性,易出问题,一旦出现磁盘坏道,容易出现不可逆转的数据丢失。 人工数据恢复困难、耗时、耗力。
安全,需要另外购买清洗和黑洞设备,需要单独实现安全机制。
成本,存储受硬盘容量限制,需人工扩容,单线或双线接入速度慢,有带宽限制,峰值时期需人工扩容。需专人运维,成本高。数据处理能力,需要额外采购,单独部署。并且oss有强大的可扩展,与灵活性,我们可以使用ossfs这样成熟的oss辅助工具,直接将bucket挂载在ECS主机上提供服务,省去了bucket外网域名与CDN回源的设置环节,当然也看各业务的不同,如果迁移oss后的改动量大的话,推荐使用这种方法,这一次迁移我们选择挂载oss的方法。
二、现有环境
我们产品以音频书籍为主,所以在静态节点的资源量上非常庞大。我们将数据分成十份,分散在十个node上,每个node挂载有十分之一的资源。其中每两台node节点通过NFS共享一块32T存储块,以单数node为NFS的mount master node,双数node为NFS的mount slave node。
用户通过静态资源负载均衡器接口统一调用mp3文件,设置CDN回源地址为静态资源接口,SLB做七层转发至/res/upload/cdn/node*各节点拼接url。此url为线上音频返回用户的明文weburl,存储在数据库。例如url:
https://hmf-res-cdn.kting.cn/res/upload/cdn/node1/kting_huawei_fm/amp/user_11632/audio_original/20181128/3ttskmcjd.mp3
三、迁移前夜
首先需要考虑的几点因素:
- 时间问题,抽取什么时间段进行迁移数据可以不影响到线上服务。
- 还是时间问题,什么样的方式迁移可以以最快速度的完成,赶在共享存储块商业化之前。
- 费用问题,全部的迁移过程会有费用产生吗。
- 增量数据问题,怎么可以保证数据量的同步。
- 发布问题,数据迁移之后,要准备上线工作,怎么能做到平滑的上线工作,将灰度降到最低。
带着这些问题,准备开始迁移工作。
四、开始迁移
1.1使用单机模式ossimport
https://help.aliyun.com/docum...
下载ossimport.zip
分发zip文件
$ cat /data/salt/init.sls
ossfs-file:
file.managed:
- source: salt://ossfs/ossimport-2.3.2.zip
- name: /opt/ossimport-2.3.2.zip
- user: root
- group: root
$ salt -N 'hmf_res' sate.sls init
1.2配置job.cfg
$ cat conf/local_job.cfg
#是否打开增量模式,如果设为true,会每间隔incrementalModeInterval(单位秒)重新扫描一次增量数据,并将增量数据同步到oss上,incrementalModeInterval不建议配置成小于3600秒的值,会浪费很多请求次数,造成额外的开销(目前可配置的最小间隔为900秒)
isIncremental=true
incrementalModeInterval=21600
##############################################################同步源端设置##############################################################
#同步源类型,目前支持:
#1.local(本地文件,此选项只需要填写srcPrefix,不需要填写srcAccessKey,srcSecretKey,srcDomain,srcBucket)
#2.oss(从oss的一个bucket迁移到另一个bucket)
#3.qiniu(七牛)
#4.bos(百度的云存储)
#5.ks3(金山的云存储)
#6.s3(亚马逊s3)
#7.youpai(又拍云,又拍云获取文件列表的接口比较特殊,在同步时list不支持断点,因此在list没有完成时杀掉同步进程会导致下次会重新全部list文件列表)
#8.http (通过提供的http链接列表同步数据,此选项不需要填写srcAccessKey,srcSecretKey,srcDomain,srcBucket,srcPrefix)
#9.cos(腾讯云)
#10.azure(微软blob)
srcType=local
#源access key,同步本地文件以及通过http地址同步的不需要填,大部分云平台填写控制台获取的acceess key/accss key id,又拍云填写操作员账号
srcAccessKey=
#源secrect key,同步本地文件以及通过http地址同步的不需要填,大部分云平台填写控制台获取的secret key/access key secret,又拍云填写操作员密码
srcSecretKey=
#源endpoint,同步本地文件以及通过http地址同步的不需要填
#1.oss: 从控制台获取域名(非带bucket前缀的二级域名),域名列表参考https://help.aliyun.com/document_detail/31834.html; 例:"srcDomain=http://oss-cn-hangzhou-internal.aliyuncs.com"; 如果用阿里云ecs虚拟机做迁移的,请使用internal域名,不计费且不受虚拟机带宽限制(非虚拟机无法使用);例:http://oss-cn-hangzhou-internal.aliyuncs.com
#2.七牛: 从七牛控制台获取对应bucket的域名
#3.百度bos: http://bj.bcebos.com或者http://gz.bcebos.com
#4.金山ks3: http://kss.ksyun.com或者http://ks3-cn-beijing.ksyun.com或者http://ks3-us-west-1.ksyun.com
#5.亚马逊s3: 各个region的地址请参考http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
#6.又拍云: http://v0.api.upyun.com(自动判断最优线路)或者http://v1.api.upyun.com(电信线路)或者http://v2.api.upyun.com(联通网通线路)或者http://v3.api.upyun.com(移动铁通线路)
#7.腾讯云: cos v3版本不需要填写;cos v4版本需要填上bucket所在的区域,比如华南园区填写:gz,华北园区:tj,华东园区:sh
#8.微软blob: 连接字符串中的EndpointSuffix,如core.chinacloudapi.cn
srcDomain=
#源bucket名字,同步本地文件以及通过http地址同步的不需要填,不需要加上"/";微软blob填container名称
srcBucket=
#源前缀,默认为空,如果srcType=local,则此目录是本地目录,如果是其他类型,则是源Bucket里需要同步的Object的前缀,注意如果是本地目录,需要完整目录路径(以'/'进行分割并且以'/'结尾,例: c:/example/)
srcPrefix=/resource_nginx/res/upload/cdn/node1/
##############################################################同步目的端设置################################################################
#目的 access key
destAccessKey=xxxxxxxxx
#目的 secret key
destSecretKey=xxxxxxxxxxxxxxxxxxxxxxx
#目的endpoint,请根据您的实际oss区域填写,默认为杭州的域名,如果用阿里云ecs虚拟机做迁移的,请使用internal域名,不计费且不受虚拟机带宽限制(非虚拟机无法使用);例:http://oss-cn-hangzhou-internal.aliyuncs.com
#注意:域名里不要带上bucket前缀,oss域名帮助页面:https://help.aliyun.com/document_detail/31837.html
destDomain=http://oss-cn-shanghai-internal.aliyuncs.com
#目的bucket,不需要加上"/"
destBucket=hmf-res-node1
#目标前缀,默认为空,直接放在bucket下(如果要将数据同步到oss的某个目录下,请以'/'结尾),注意:oss不支持以 '/' 作为文件的开头,所以destPrefix请不要配置以'/'做为开头
#一个本地文件路径为 srcPrefix + relativePath的文件,迁移到oss的路径为destDomain/destBucket/destPrefix + relativePath
#一个云端文件路径为 srcDomain/srcBucket/srcPrefix + relativePath的文件,迁移到oss的路径为destDomain/destBucket/destPrefix + relativePath
destPrefix=res/upload/cdn/node1/
##############################################################srcType=cos时的配置项###########################################################
#腾讯云的appId
appId=0
##############################################################srcType=youpai时的配置项########################################################
#又拍云存储数据迁移文件是否从CDN下载。又拍云云存储下载操作默认限速,影响数据迁移速度;如果配置了CDN,可以从云存储上获取迁移文件的列表,数据从CDN上下载。cdnHost+key即为下载地址。
isDownloadFromCdn=false
cdnDomain=
##############################################################srcType=http时的配置选项########################################################
#srcType="http"时,需要提供http列表文件的绝对路径,此文件中的http链接需要划分成两列,分别代表前缀以及上传到oss后的相对路径
#例,有一个完整的http链接是127.0.0.1/aa/bb.jpg,不同的切分方法最后会导致上传到oss的路径会不一样:
#c:/example/http.list文件内容:
#127.0.0.1/aa/ bb.jpg
#127.0.0.1/ aa/bb.jpg
# 第一行的文件导入到oss后的路径为 "destDomain/destBucket/destPrefix" + "bb.jpg"
# 第二行的文件导入到oss后的路径为 "destDomain/destBucket/destPrefix" + "aa/bb.jpg"
httpListFilePath=c:/example/http.list
httpPrefixColumn=1
relativePathColumn=2
##############################################################任务配置,没有特殊需求不需要修改#################################################
#job名字,每个任务唯一,单机模式下请不要修改此项
jobName=local_test
#job类型(import/audit),import为同步数据到oss,audit为校验源端数据和oss数据是否一致
jobType=import
#只导入源文件最后修改时间大于该时间的数据,默认为0,这个时间为unix时间戳(秒数)
importSince=0
#在校验时,如果文件的最后修改时间大于该值,则跳过此文件的校验,默认值0为关闭该功能,所有文件都需要校验,这个时间为unix时间戳(秒数),jobType为audit时此项不生效
lastModify=0
#数据迁移时,是否跳过已经存在的文件。当设置为true时,根据文件的size和LastModifedTime判断是否跳过;为false时,总是覆盖OSS上已有文件。jobType为audit时此项不生效。
isSkipExistFile=true
# 每个子任务最大的文件个数限制,这个会影响到任务执行的并行度,一般配置为总的文件数/120
taskObjectCountLimit=10000
#每个子任务下载的最大文件大小限制(bytes)
taskObjectSizeLimit=1000000000
#并行扫描文件列表的线程数,只影响扫描文件的效率,没有特殊需求不要修改
scanThreadCount=1
#最大允许并行扫描目录的深度,默认为1就是只能在顶级目录间并行扫描,没有特殊需求不要修改,随意配置的过大会导致任务无法正常运行
maxMultiThreadScanDepth=1
#单个大文件分片上传并发数,默认超过150MB为大文件,分片为50MB,srcType=local时有效,其它情况该配置项无效
uploadThreadNumPerLargeFile=3
#大于该值的文件使用分片上传,否则使用普通上传,请配置大于1MB以上;有效配置值如:50m/1024m/5g
multipartUploadThreshold=150m
#分配上传时分片大小,请配置大于100k的数据,否则无效,采用默认值50MB;有效配置值如:500k/50m/2g
multipartUploadPartSize=50m
#存储在OSS上的数据否加密,默认不加密
isServerSideEncryption=false
#local模式时,链接文件是否上传,默认不上传
isAllowSymbolicLink=false
# 七牛云存储获取Meta的方式,有效值head和stat,默认使用stat;head通过HTTP HEAD请求获取,stat通过BucketManager.stat
getObjectMetaMode=stat
#数据迁移后是否进行数据的正确性校验,默认校验
isAuditAfterImport=true
#数据校验方式,有效值为simple/general/detailed,默认值general;simple只校验文件的size,general校验文件的size/lastModify/header,detailed检验文件的CRC或MD5,开发中
auditMode=general
更改内容部分如下:
isIncremental=true
incrementalModeInterval=21600
srcPrefix=/resource_nginx/res/upload/cdn/node1/
destAccessKey=xxxxxxxxx
destSecretKey=xxxxxxxxxxxxxxxxx
destDomain=http://oss-cn-shanghai-internal.aliyuncs.com
destBucket=hmf-res-node1
destPrefix=res/upload/cdn/node1/
isSkipExistFile=ture
开启了增量模式
,以6个小时的循环时间
,在时间段的选择上以及配合sys文件中的workerMaxThroughput
选项不会对线上服务产生影响。并且也打开了判断已存在文件的选项
为true。
数据目录以node\*目录为明显分界
,划分bucket设置源目录到node*,oss目标目录要以源目录通过七层转发后的数据目录结构一致
。
accesskey与secretkey是阿里云账号的唯一访问秘钥,在控制台面板账户头像下有accesskey按钮可以获得。它是权衡oss是否公开或私有提供服务的通道。
1.3配置sys. properties
只更改一项:
workerMaxThroughput(KB/s)=51250
限制最大传输流量,因为在现有环境中,每两台node是通过nfs进行网络存储的,它通过内网交互,巧的是,阿里云以地域划分网络
,属于同一经典网络地域是通过内网通信的
,也就是说10台node是通过内网与oss进行迁移。但在测试环节中,发现ossimport启动后对流量是没有限制的,会直接将内网带宽跑满
,导致内网间服务器与服务器通讯失败
,要避免只能先迁移nfs slave节点,如果先迁移nfs master节点话,内网带宽跑满,网络存储会没有响应,对于线上来说nfs slave节点mp3数据文件等于宕掉
,返回状态码502
。
内网传输,我们解决了费用问题,说明在整个迁移过程中,是不会有费用产生的。
这又是一笔时间成本的问题,有三个方案:
- 先迁移完slave节点之后,还需将master,slave角色互换后再进行迁移,
- 在backup服务器中搭建ossimport迁移备份中的nfs
master节点,但ossimport只可以跑一个job,多job工作是不支持的,也就是多个源目录迁移。 - 从ossimport上寻找原因,想办法限制迁移带宽,让迁移过程中不影响内网通讯,从而可以做到"火力全开"。更改workerMaxThroughput的值也就是采取这一方案的原因。这样全部节点都可以在规定时间段内开始迁移,时间成本上达到均衡。
分发配置文件
$ salt-cp -N 'hmf_res' local_job.cfg /data/server/ossimport/conf/local_job.cfg
$ salt-cp -N 'hmf_res' sys.properties /data/server/ossimport/conf/sys.properties
2.1抽取时间段启动ossimport
抽取每天0点到6点与13到17点
流量较低的时间段进行迁移。
$ crontabe -e
0 0-6 * * * salt -N 'hmf_res' cmd.run '/data/server/ossimport/import.sh'
0 13-17 * * * salt -N 'hmf_res' cmd.run '/data/server/ossimport/import.sh'
2.2观察job日志是否正常
job启动后在$OSSIMPORT_HOME/logs/job.stat.log
有实时的迁移状态输出,通过这里可以观察到剩余的未完成线程
---------------- job stat ------------------
JobName:local_test
JobState:Running
PendingTasks:782
DispatchedTasks:1162
RunningTasks:74
SucceedTasks:0
FailedTasks:0
ScanFinished:false
RunningTasks Progress:
9AE4A4587A50C1E025DC75507150572F_1543478694125:1001388038/1001388038 101/101
072CCCEDE220FC1AF9436F75C4CF09DC_1543478689101:1000168397/1000168397 43/43
A805C8D5402A92BEC3DA7157B54D54C7_1543478696407:1007872906/1007872906 98/98
3E6DDC612342BDA379D16330ECCAC200_1543478690703:1003686291/1003686291 36/36
0D69C2C9D02FF630E5ED169A1A935049_1543478691589:1011642606/1011642606 30/30
48F98879A6CD3A502F81646DA1A60F56_1543478696871:1015556530/1015556530 96/96
E19B1B3BACD79E64A387BC6929C984ED_1543478697556:1017042946/1017042946 99/99
47CE6608AFEC7B4969DA98762C56D758_1543478697547:1002425626/1002425626 99/99
E42B7D4B9F68195334A5E707BA4F1AE5_1543478697222:1001794526/1001794526 94/94
......
迁移结束后,如果开启增量模式,在import.log文件输出中会显示:
[2018-11-29 16:24:26] [JobTracker] [INFO ] - [2018-11-29 16:24:26] [JobTracker] [INFO ] - ================ Jobs Status =================
[2018-11-29 16:24:26] [JobTracker] [INFO ] - JobName:local_test
[2018-11-29 16:24:26] [JobTracker] [INFO ] - JobState:RUNNING
[2018-11-29 16:24:26] [JobTracker] [INFO ] - Pending Task Count:0
[2018-11-29 16:24:26] [JobTracker] [INFO ] - Dispatched Task Count:2331
[2018-11-29 16:24:26] [JobTracker] [INFO ] - Succeed Task Count:2331
[2018-11-29 16:24:26] [JobTracker] [INFO ] - Failed Task Count:0
[2018-11-29 16:24:26] [JobTracker] [INFO ] - Is Scan Finished:false
Dispatced Task Count与Succeed Task Count完成线程数一致
2.3观察控制台信息与带库占用情况
$ find /resource_nginx/res/upload/cdn/node1/ | wc-l
根据系统统计得到总文件数量。
从控制台上不断刷新可以明显看到文件数量的实时状态,但其他可监控项是有1-2小时的延迟抓取。
发现未超过所限流量,带宽正常,并且尝试访问nfs slave节点的音频数据,weburl正常返回,说明迁移过程带宽未影响到内网服务器
等待全部数据迁移完成,进行下一步ossfs挂载
3.1使用ossfs挂载bucket
将rpm包分发至10台node,具体安装方法可以参考下面阿里官方文档,有详细的过程。
https://help.aliyun.com/docum...
3.2平滑挂载oss
在之前我们提到一个问题,是关于增量数据的。这里我们将数据分为两部分,T1数据与T2数据
。T1数据已经在第一次大规模迁移中完毕;剩下的数据是在触发6小时增备前的数据,这一部分基本很少,每个节点应该有300~400的文件数量,此数据称之为T2数据
①已经结束的迁移在未触发增量前,结束job。
$ jps
2341 ossimport.jar
$ kill -9 2341
②创建新目录,预备卸盘之后的第二次迁移T2数据的工作
$ mkdir /T2data
$ vim conf/local_job.cfg
srcPrefix=/T2data/res/upload/cdn/node2/
此路径是存在增量数据的原硬盘,等待挂载成功后开始迁移T2数据
③逐降10台node中SLB权重值,平滑服务
④卸载硬盘
$ lsof -n | grep resource_nginx
$ /etc/init.d/nfs stop
查看进程占用目录情况,关闭nfs服务
$ umount /resource_nginx
$ du -sh /resource_nginx/*
确保目录下已经清空
$ rm -rf /resource_nginx/*
⑤挂载oss bucket
$ ossfs hmf-res-node1 /resource_nginx/ -ourl=http://oss-cn-shanghai-internal.aliyuncs.com -o allow_other
执行完毕后,恢复此节点权重值,跟踪nginx访问日志http状态码
$ tail -f /data/logs/nginx/node_access.log
⑥返回状态码200 202 304,确保无误后,迅速挂载原硬盘,迁移T2数据
$ mount /dev/vdc1 /T2data
$ du -sh /T2data/res/upload/cdn/node1/*
确保无误,启动job
$ sh import.sh
调整权重,逐个迁移其他node
五、全部节点迁移完成后,进行结尾工作
①自动挂载
echo "ossfs#hmf-res-node1 /resource_nginx fuse _netdev,url=your_url,allow_other 0 0" >> /etc/fstab
其他节点依次类推
②至此迁移的全部实战过程就结束了,剩下的时间就是监控数据的变化,策划未来oss备份工作,数据可贵,云厂商的产品虽好,但一定要有数据一直存在于本地,所以从云上备到云下也是必不可少的过程,当然这里我提供大家三个方案,具体实施就不在阐述:
- 自行在业务端写入OSS数据时设置双份写入,保证多数据中心的Bucket均同步存储业务数据,由您自己完成备份功能。
- 将OSS中的数据同步或者异步下载到您本地您自己进行备份。具体需要调用OSS的API/SDK接口,请您参考:https://help.aliyun.com/docum...
- OSS本身提供跨区域复制功能,可以将一个Bucket中的全量和增量数据异步地复制到其他数据中心的Bucket中,同时关闭源Bucket的增删改操作同步到目标Bucket。您可以参考下:https://help.aliyun.com/docum...
每个公司有各自的业务特点,此方案是我公司迁移过程记录,希望可以帮到大家进一步了解新产品,可以尽快开展学习。感谢阿里云提供计算服务,数据可贵,操作谨慎!