KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

07 · 站点迁移与重构:可回滚的映射工程 — keel 龙骨

本章目标:把站点迁移当成一次有清单、有映射、有验证、有回滚的数据一致性工程。 验收标准:301 映射覆盖 100% 旧 URL、抽样全通过,迁移后有流量曲线判读与回滚预案。

本章目标:把站点迁移当成一次有清单、有映射、有验证、有回滚的数据一致性工程。
验收标准:301 映射覆盖 100% 旧 URL、抽样全通过,迁移后有流量曲线判读与回滚预案。

为什么迁移是高危操作:迁移把"URL 是稳定的"这个前提一次性打破。旧 URL 的权重、外链、收录都要重新对齐。做错一次,可能损失数月积累。因此它必须像数据库迁移一样严肃:先生成映射、再验证、再切流、再观察、可回滚。


一、迁移的类型与风险

类型 例子 风险
域名更换 A 域 → B 域 高,需全量重定向与 GSC 改址
协议变更 http → https 高,混合内容与 canonical
结构重构 /p?id= → /courses/x/ 高,需 1:1 映射
平台迁移 换 CMS/框架 中高,URL 易被打乱
目录调整 /old/ → /new/ 中,局部重定向

唯一安全的做法:旧 URL 全集 → 新 URL 全集的 1:1 映射,一条都不能漏。


二、迁移检查清单

迁移前:

迁移中:

迁移后:


三、301 映射的生成

# 1) 从旧 sitemap 与日志汇总旧 URL 全集
curl -s https://old.xxxxxx.cn/sitemap.xml | grep -oE '<loc>[^<]+' | sed 's/<loc>//' | sort -u > /tmp/old.txt
grep -iE 'googlebot|bingbot' /var/log/nginx/old.access.log | awk '{print $7}' \
  | sed 's#^#https://old.xxxxxx.cn#' | sort -u >> /tmp/old.txt
sort -u /tmp/old.txt -o /tmp/old.txt
wc -l /tmp/old.txt

# 2) 生成映射表(此处用规则推导,实际项目可用脚本按规则批量生成)
awk '{print $0"\thttps://www.xxxxxx.cn"$0}' /tmp/old.txt > /tmp/redirect.map

生成的 nginx 配置:

# /etc/nginx/conf.d/redirects.conf
map $request_uri $new_uri {
  default                           /;
  ~^/p\?id=87$                      /learning/courses/tools/lessons/1/;
  ~^/old/courses/(.*)$              /learning/courses/$1;
  ~^/learning/courses/tools/lessons/1$  /learning/courses/tools/lessons/1/;
}

server {
  server_name old.xxxxxx.cn;
  return 301 https://www.xxxxxx.cn$new_uri;
}

规则:

  1. 单跳直达:old → new,不要 old → 中间 → new。
  2. 保留参数语义:有搜索价值的参数要么保留要么归并,不要一律丢。
  3. 顺序无关:nginx map 用正则匹配,注意优先级。

四、映射的验证

验证必须量化,不能靠人工点几个:

# 抽样 100 条旧 URL,检查是否 301 到预期的新 URL
fail=0; total=0
while read -r old; do
  total=$((total+1))
  code=$(curl -s -o /dev/null -w '%{http_code}' "$old")
  loc=$(curl -s -o /dev/null -w '%{redirect_url}' "$old")
  if [ "$code" != "301" ]; then
    echo "❌ $old → $code"; fail=$((fail+1))
  fi
done < <(shuf -n 100 /tmp/old.txt)
echo "抽样 $total 条,失败 $fail 条"

覆盖率验证(最重要):

# 旧 URL 总数 vs 已配置 301 的数量
echo "旧 URL 总数: $(wc -l < /tmp/old.txt)"
echo "已映射规则数: $(grep -c '~^' /etc/nginx/conf.d/redirects.conf)"
# 两者应大致相等;差距大说明有遗漏
验证项 通过标准
覆盖率 100%(无遗漏旧 URL)
状态码 全部 301(不是 302/200)
目标 URL 全部是 200 的终址
跳数 全部单跳
参数变体 带参/尾斜杠变体也 301

五、迁移后的流量曲线判读

典型迁移曲线与判读:

阶段 现象 是否正常
D0–D3 流量下滑、抓取激增(重抓新址) 正常
D3–D14 逐步回升、新 URL 开始收录 正常
D14–D42 接近迁移前水平 正常
长期不回升 收录不回、排名丢失 异常,排查
断崖式长期下跌 多日无回升 异常,考虑回滚

异常排查顺序:

# 1) 新址是否被大量抓取
sqlite3 /tmp/seo.db "SELECT substr(ts,1,10), count(*) FROM crawl
  WHERE uri LIKE '/learning/%' GROUP BY 1 ORDER BY 1 DESC LIMIT 7;"

# 2) 301 是否大量残留(说明内链/sitemap 还在指旧址)
grep -i 'googlebot' /var/log/nginx/learning.access.log | awk '$9==301 {print $7}' | sort | uniq -c | sort -rn | head

# 3) 新址状态码是否健康
grep -i 'googlebot' /var/log/nginx/learning.access.log | awk '{print $9}' | sort | uniq -c | sort -rn

六、回滚决策

什么情况回滚:迁移后超过既定观察期(如 6 周)且核心词排名与流量仍未恢复,且已排除技术故障。回滚本身也是一次迁移,需要同样严谨。

回滚触发条件 动作
6 周无回升 + 技术无故障 评估回滚
映射遗漏 >5% 且无法快速补 回滚修映射
新架构无法在合理时间内修好 回滚
短期波动(<2 周) 不回滚,继续观察

回滚的纪律:保留旧站可用状态,回滚 = 恢复旧站 + 撤销 301 + 提交旧 sitemap。不要在原状不明时仓促回滚,先确认不是可修的技术问题。


七、故障速查

现象 原因 处理
大量 404 出现在新址 映射遗漏 补 301
权重没传过来 用了 302 或跳数过多 改 301 单跳
排名不恢复 内链仍指旧址 全站更新内链
收录数骤降 sitemap 未提交/错误 重新提交新 sitemap
部分页流量正常部分归零 局部映射缺失 定位缺失目录

八、本章验收

# 本章核心两连
wc -l < /tmp/old.txt
grep -i 'googlebot' /var/log/nginx/learning.access.log | awk '$9==301' | wc -l

迁移解决"结构怎么变"。下一章回到内容本身:如何让内容成体系、建立主题权威。

进入 keel 阅读