138 大美业是收购的美业招聘平台,需要整体迁移到我们的技术平台。涉及 PC 站、H5、微信小程序、招聘通小程序四个端,用户、企业、职位、简历数据都要迁移。2024年9月完成了全站迁移,今天把实战经验分享出来。

一、迁移范围

  • 用户数据:138 用户 50万+,合并到主平台用户体系
  • 企业数据:企业 2万+,企业信息、资质、认证状态
  • 职位数据:在招职位 5万+,历史职位 50万+
  • 简历数据:求职者简历 30万+
  • 四端切换:PC、H5、微信小程序、招聘通小程序

二、数据迁移方案

账号合并

138 用户和主平台用户用手机号做唯一标识去重:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
func migrateUsers() error {
    // 1. 从旧库读用户
    oldUsers := queryOldUsers()

    for _, oldUser := range oldUsers {
        // 2. 按手机号查主平台是否已有用户
        existUser := findByPhone(oldUser.Phone)

        if existUser != nil {
            // 已存在,合并数据(关联旧用户ID)
            mergeUser(existUser, oldUser)
        } else {
            // 不存在,创建新用户
            createUser(oldUser)
        }
    }
    return nil
}

增量同步

全量迁移需要时间,迁移期间旧系统还有新数据产生。用 Canal 监听旧库 binlog 做增量同步:

binlogCanalKafka

全量迁移完成后,增量同步追平,然后切换流量。

数据校验

迁移完成后做数据校验:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func validate() error {
    // 1. 数量校验:新旧库记录数对比
    oldCount := countOldUsers()
    newCount := countNewUsers()
    if oldCount != newCount {
        return errors.New("user count mismatch")
    }

    // 2. 抽样校验:随机抽1000条对比字段
    samples := randomSample(1000)
    for _, sample := range samples {
        oldData := getOldUser(sample.ID)
        newData := getNewUser(sample.NewID)
        if !reflect.DeepEqual(oldData, newData) {
            return errors.New("data mismatch: " + sample.ID)
        }
    }
    return nil
}

三、灰度切换方案

按端逐步切换,每个端观察 3 天:

  1. 第一阶段:招聘通小程序切换(流量最小,风险最低)
  2. 第二阶段:微信小程序切换
  3. 第三阶段:H5 切换
  4. 第四阶段:PC 站切换(流量最大,最后切)

每个阶段用 Nginx 按比例灰度:

1
2
3
4
5
# 10% 流量走新系统
split_clients "${remote_addr}${request_id}" $backend {
    10% new_system;
    * old_system;
}

观察错误率、响应时间、用户投诉,没问题后逐步调到 50%、100%。

四、回滚预案

每个阶段都有快速回滚预案:

  • Nginx 配置一键切回旧系统
  • 新系统写入的数据通过增量同步回旧库(双写期间)
  • 回滚后用户无感知

五、踩坑经验

  1. 手机号重复:旧系统有手机号重复的脏数据(同一个手机号注册了多个账号),合并时要处理冲突。方案:保留最新的账号,旧账号的职位/简历关联到新账号
  2. 密码加密方式不同:旧系统用 md5,新系统用 bcrypt。方案:保留旧密码 hash,用户首次登录时验证旧密码后自动升级为 bcrypt
  3. 小程序 AppID 不同:138 小程序和主平台小程序是不同的 AppID,用户的 openid 不一样。方案:用手机号做用户合并,openid 作为第三方账号绑定
  4. 历史数据关联:旧系统的职位/简历关联的用户ID,迁移后要映射到新用户ID。用映射表记录 old_user_id → new_user_id,迁移职位/简历时替换
  5. 切换期间数据不一致:灰度期间新旧系统都有写入,数据可能不一致。用双写 + 对账脚本每天校验,不一致的数据自动修复

六、总结

全站数据迁移核心:

  1. 全量+增量:全量迁移历史数据,Canal 监听 binlog 做增量同步,保证迁移期间不丢数据
  2. 数据校验:数量校验 + 抽样校验,确保迁移数据准确
  3. 按端灰度:按端逐步切换,每个端观察验证,降低风险
  4. 双写过渡:切换期间双写新旧系统,保证回滚后数据不丢
  5. 回滚预案:每个阶段都有一键回滚方案,出问题快速恢复
  6. 脏数据处理:旧系统的重复数据、格式不规范数据要提前清洗

数据迁移是个高风险操作,核心是"稳"——能灰度就不全量,能双写就不单写,能校验就不假设。迁移前做好方案和预案,迁移中做好监控和校验,迁移后做好验证和对账。宁可慢一点,也不能出数据丢失或不一致的问题。