线上数据修复手册

前言

来到这个页面的童鞋,首先恭喜你已经有足够的资格来处理线上数据了,至少已经开始需要关注对线上数据的修复了。下面我们将会一起探讨一下线上数据修复那些事儿。


背景

线上数据,顾名思义是公司production环境中真实的数据,不同于dev、staging、uat等其他环境的数据,这里的数据是真实用户直接可以访问的到的。由于系统升级、代码改造、不同团队之间的服务欠缺兼容性、代码bug…等这样那样等原因,我们无可避免的会有一些数据修复的事情要做。


工作手顺

事前准备

  1. 需要确定我们修复数据的目标介质:

    1. RDS(Relational Data Service)

    包括常见的MySql、Hive,甚至还有SQLite……这些各种开源不开源的各种方案

    1. NoSql

    比如MongoDb、Hbase、ES……还有最近比较火的TiDB之类的
    当然了,某种意义上说Redis也可以认为是一种NoSql的服务

    1. 消息队列

    消息队列当使用本身是为了应对突然暴涨的数据量,俗称削峰填谷。但是如果因为服务的亚健康或者停摆造成了数据的积压,那么在服务重新部署、hotfix只后可能会出现潴留在消息队列里的数据与当前处理逻辑不兼容的情况
    常见的消息队列,如Kafka、RocketMQ、ActiveMQ等

    1. OSS系统

    除了上述的“热”数据之外,可能还有不少已经做备份的离线数据进入了各类OSS(Object Storage Service,甚至牛逼的还会有各类离线系统,比如磁带机…)

  2. 需要先通过技术手段确定数据修复影响的数据量:

    比如:
    select count(1) from db.table where ${conditions}
    db.collection(x).count({conditions})
    

建议针对不同量级的数据采取不同的修复策略,毕竟不同的数据量在修复、生效、验证和回滚等的操作需要的时间会相差很远,越长的操作时间会产生越大的风险。

  1. 针对不同的数据修复操作设计相对应的修复方案

    1. 直连数据库手动修改:

      • 优势:
        • 直接修改线上数据,见效快,立等可取,可以立刻解决一些由于数据错误带来的业务停顿
        • 不容易因为意见不合而导致修复操作受阻
      • 劣势:
        • 对每一条操作的准确性要求很高,修改直接生效,任何失误都会直接影响到所有关联业务
        • 临时可用行为,如果出现大量的这类操作会对业务数据的可信度带来很大影响
        • 会隐藏很多因为逻辑、设计、代码实现等全链路的失误,造成早期开发时候的懒惰
    2. 提交修复脚本:

      • 优势:
        • 可以有一到多层的review,可以减少(不是完全杜绝)类似drop table这种大规模杀伤性破坏
        • 把相关同事一起拉下水,万一修复操作出现了问题,相关同学不说一起背锅也可以相互做个证
      • 劣势:
        • 效率较低,需要层层review,可能会对急需热修复的业务带来更大的delay
        • 有可能会因为站不同立场的reviewer而block住修复计划,毕竟有人的地方就会有不同意见
    3. 备份修复并重定向:

      • 优势:
        • 更常见于时效性要求不高或者数据量特别大的数据修复,e.g. 将几十万条数据中某个枚举值做替换以兼容新的业务逻辑.etc.
        • 不影响当前线上业务,特别是使用双写甚至多写的策略的情况下,进行重定向时几乎是业务无感知的
        • 对于消息队列里数据的修复目前一般也使用这种方式,消费–》修改–》重新写入新topic–》topci迁移
      • 劣势:
        • 时效性更差,一般修复都是T+1甚至T+N的
        • 需要准备跟受影响数据同样甚至更大的存储空间,同时执行修复脚本,会大大的增加程序/服务的复杂程度

制定修复计划

  1. 数据处理脚本准备
    1. 目标数据获取脚本
    2. 数据修复脚本
    3. 数据验证脚本
    4. 数据回滚脚本
  2. 数据处理脚本review
  3. 数据处理脚本本地测试
  4. 数据处理脚本staging环境测试
  5. 数据处理脚本prd环境应用
  6. 数据验证和回滚策略

数据修复实施

  1. 数据处理脚本部署
  2. roling deploy
  3. 逐步切换线上数据访问流量
  4. 对每个节点进行数据监控及验证
  5. 尽早发现数据修复异常并及时回滚
  • 数据回滚的优先级要大于修复的优先级
  • 因为数据回滚到未修复状态,至少还能让程序运行的差强人意
  • 如果强行进行数据的修复,很有可能在影响当前业务流转的同时,引入新的数据issue,带来不必要的风险

在进行数据修复时,需要两个人甚至多个人同时在场(在线),同时主要操作者需要在进行每个操作时,对每个check point做到手到口到心到,可以参考这一篇


数据修复验证

  1. 是否规划中影响到的数据都已经修复完成
  2. 有没有影响到非目标数据
  3. 有没有影响到非目标关联服务
  4. 修复之后未来还会不会出现类似的数据问题

修复完成

复盘

良心拷问三连:是什么?为什么?怎么办?

  1. 数据问题产生的原因
  2. 影响范围
  3. 造成的损失
  4. 发生的原因
    • 主观的
    • 客观的
  5. 挽救措施
  6. 监控及预警机制
  7. 规避策略
  8. 修复过程中遇到的“事故”和”教训“
  9. 教育&惩罚
    • 请全组人喝奶茶
    • 平板支撑
    • “黑历史”X连拍

注意点:

优先级:

  1. 数据准确性
  2. 影响范围
  3. 再次出现的可能性
  4. 修复的速度
  5. 操作的便利性
能用脚本跑的就不手动敲命令!
能用脚本跑的就不手动敲命令!
能用脚本跑的就不手动敲命令!
重要的事儿说三遍

其他碎碎念

  1. 数据修复不同于新机能的上线、bug的修改,是一个十分考验胆大心细的过程,需要:

    • 事前详细的规划
    • 事中谨慎的每一步操作以及严格的验证
    • 事后需要及时的复盘
    • 制定详细的监控、预警和规避措施
  2. 与此同时,数据的修复可能会带来很多意想不到的兼容性问题,影响到很多不曾预料到的关联服务、团队,要记得:

    • 在修复速度和数据准确性的权衡之中,优先考虑的是数据的准确性
    • 少量多次的修复要远远好于大批量的操作,把影响范围
    • 验证中发现异常最高优先级的是回滚而不是继续执行
  3. 上线新功能可能会帮公司赚更多钱,帮你收获更多的项目奖金,而修复bug甚至修复数据可能仅仅是让大家少亏钱而已,但是不管是支付还是任何模块里面,数据修复都是最后一道防线,轻易不能动用,动用了就要出效果。需要来回来去的修复的话,不管是流程还是代码甚至是修复人的操作里面肯定出问题了,请全组人喝奶茶的事儿是跑不掉了,不然跟你没完!

你可能感兴趣的:(运维)