【前言】

       我们是做的国外的项目,最开始的时候调研在国外亚马逊云在可靠性等方面还是具有很大优势,于是我们的项目都部署在亚马逊云上;

       我们业务发展十分不错,随着项目越来越大,用到的机器越来越多,同时亚马逊的成本也在不断攀升;最近一段时间我们又针对国外市场进行了各方面(成本,可靠性等)进行调研,最终决定将所有业务及数据从亚马逊云迁移至阿里云;当然迁移也是个有挑战的事情;要做到不能出任何差错,各个技术团队配合(运维负责进行环境搭建,数据迁移;开发负责各个工程的检查;测试负责回归测试.....)

       今天与大家分享的是我们数据迁移其中的一部分Redis数据迁移的一种备用方案;

【迁移方法】

       一、数据量:

              数据条数:550万+,数据大小:450MB 

       二、迁移:

             1、亚马逊自带redis--->阿里云自带redis

            2、自带redis和自建redis区别:自带redis是云服务器上本身应用,自建redis是在云服务器上自己安装redis服务;自带redis的优点:可靠,省事,出故障后恢复快;自建redis优点:可控;

            3、Redis迁移标准:(1)数据不能丢失错乱;(2)迁移时间必须够快(按照整体迁移的进度来看,redis迁移必须控制在一个半小时以内);

       三、两种方案及实现:

              1、两种方案:

                 (1)Redis自带备份恢复策略---rdb

              (2)通过程序(python 版本2.x,如果是3.x版本可以参考

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# 把redis里面一个数据库的东西,迁移到另外一个数据库里面
# 建立两个redis连接
# 获取到所有的key .keys()
# 判断key的类型 string\hash\list\set

import redis
#redis_from源数据,redis_to目标数据  redis_from——>redis_to
redis_from = redis.StrictRedis(host='ip',port=6379,password='',db=10)
redis_to = redis.StrictRedis(host='ip',port=6379,password='',db=10)

if __name__ == '__main__':
    cnt = 0
    scnt = 0
    lcnt = 0
    setcnt = 0
    hcnt = 0
    
    for k in redis_from.keys():
        # 循环keys里面每一个key

        data_type = redis_from.type(k)
        # 判断key的类型 string\hash\list\set

        if data_type == 'string':
            v = redis_from.get(k)
            t = redis_from.ttl(k)
            redis_to.set(k, v)
            if int(t) > 0:
                redis_to.expire(k,t)

            scnt = scnt + 1

        elif data_type == 'list':
            values = redis_from.lrange(k, 0, -1)
            t = redis_from.ttl(k)           
            redis_to.lpush(k, values)
            if int(t) > 0:
                redis_to.expire(k,t)

            lcnt = lcnt + 1
        elif data_type == 'set':
            values = redis_from.smembers(k)
            t = redis_from.ttl(k)
            redis_to.sadd(k, values)

            if int(t) > 0:
                redis_to.expire(k,t)
            setcnt = setcnt + 1
        elif data_type == 'hash':
            hcnt = hcnt + 1
            keys = redis_from.hkeys(k)                        
            for key in keys:
                value = redis_from.hget(k, key)
                t = redis_from.ttl(k)
                redis_to.hset(k, key, value)
                if int(t) > 0:
                    redis_to.expire(k,t)

        else:
            print 'not known type'
            print data_type
            file_object = open('/data/thefile.txt','a+')
            file_object.write(data_type)
            file_object.write('\n')
            file_object.close( )



        cnt = cnt + 1

    print 'total', cnt
    print 'string', scnt
    print 'list', lcnt
    print 'set', setcnt
    print 'hash', hcnt

                 (3)两种方案各自优点:

                          ①rdb方案:简单,速度快,可靠性高

                          ②程序方案:rdb不能用的情况下备胎

              2、最终方案确认                

                 (1)考虑到各个方面肯定是rdb方案是首选,遇到问题:

                          当时运维初步研究发现亚马逊自带Redis不支持导出rdb文件,而且阿里云自带的redis不支持rdb文件导入;

                 (2)直接用程序将亚马逊云的自带redis数据读到阿里云自带redis中,遇到问题:

                          数据量大,时时刻刻需要跨网传输,需要时间长;

                 (3)经过和运维一起沟通,确定一种解决方案:

                          ①在亚马逊上搭一个自建redis;

                          ②通过程序将生产自带redis值读到自建redis;

                          ③备份亚马逊自建redis的rdb文件,拷贝并恢复到阿里云的自建redis上;

                          ④通过阿里云自带redis-sync-manager工具将阿里云的自建redis数据迁移至阿里云自带redis;

                 (4)最终多次用最终方案做实验,发现将550W+线上数据从亚马逊云自带redis同步到阿里云自带redis中用时1.2小时左右符合预期目标;

                 (5)实验中的个小疑惑:同步完后在阿里云自带redis中查看发现总少几万个key;通过将redis同步前后的key值导出来对比发现少的这几万个key正好是失效时间在1.2小时内的。

                 (6)后来运维进行深入研究后发现亚马逊云自带redis和阿里云自带redis都支持rdb文件的导入和导出,所以我们最终的方案是第一种方案用rdb方案进行备份和恢复,以上说的方案则为第二备用方案。                               

【总结】

          1、大数据时代已然来临,处理大数据量越来越成为我们程序员必须面对;

          2、不断迎接新的挑战,增加自身能力。