游客发表

如何做到不停机分库分表迁移?

发帖时间:2025-11-05 09:08:54

如何做到不停机分库分表迁移?
复制public void migrate(){      // 查询出当前表的停机***ID, 用于判断是否迁移完成      long maxId = execute("select max(id) from installed_app");      long tempMinId = 0L;      long stepSize = 1000;      long tempMaxId = 0L;      do{          try {              tempMaxId = tempMinId + stepSize;              // 根据InnoDB索引特性, where id>=? and id<?这种SQL性能***              String scanSql = "select * from installed_app where id>=#{tempMinId} and id<#{tempMaxId}";              List<InstalledApp> installedApps = executeSql(scanSql);              Iterator<InstalledApp> iterator = installedApps.iterator();              while (iterator.hasNext()) {                  InstalledApp installedApp = iterator.next();                  // help GC                  iterator.remove();                  long userId = installedApp.getUserId();                  String status = executeRedis("get MigrateStatus:${userId}");                  if ("COMPLETED".equals(status)) {                      // migration finish, nothing to do                      continue;                  }                  if ("MIGRATING".equals(status)) {                      // "被动迁移" migrating, nothing to do                      continue;                  }                  // 迁移前先获取锁: set MigrateStatus:18 MIGRATING ex 3600 nx                  String result = executeRedis("set MigrateStatus:${userId} MIGRATING ex 86400 nx");                  if ("OK".equals(result)) {                      // 成功获取锁后, 先将这个用户所有已安装的app查询出来[即迁移过程以用户ID维度进行迁移]                      String sql = "select * from installed_app where user_id=#{user_id}";                      List<InstalledApp> userInstalledApps = executeSql(sql);                      // 将这个用户所有已安装的app迁移到分库分表后的表中(有user_id就能得到分库分表后的b2b信息网具体的表)                      shardingInsertSql(userInstalledApps);                      // 迁移完成后, 修改缓存状态                      executeRedis("setex MigrateStatus:${userId} 864000 COMPLETED");                  } else {                      // 如果没有获取到锁, 说明被动迁移已经拿到了锁, 那么迁移交给被动迁移即可[这种概率很低]                      // 也可以加强这里的逻辑, "被动迁移"过程不可能持续很长时间, 可以尝试循环几次获取状态判断是否迁移完                      logger.info("Migration conflict. userId = {}", userId);                  }              }              if (tempMaxId >= maxId) {                  // 更新max(id),最终确认是免费源码下载分库分表否遍历完成                  maxId = execute("select max(id) from installed_app");              }              logger.info("Migration process id = {}", tempMaxId);          }catch (Throwable e){              // 如果执行过程中有任何异常(这种异常只可能是redis和mysql抛出来的), 那么退出, 修复问题后再迁移              // 并且将tempMinId的值置为logger.info("Migration process id="+tempMaxId);日志***一次记录的id, 防止重复迁移             System.exit(0);          }          tempMinId += stepSize;      }while (tempMaxId < maxId);  }  1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.服务器托管

    热门排行

    友情链接