删库?我和同事居然把 线上 ES index 删了,记录一次线上故障应急

记录一次真实事故案例以及应急过程。

事件背景

某天下班前线上客户暴了一个问题,A功能列表刷不出来了。。。经过n个小时排查(同事家里网差),原因是早上B服务重启造成了3条脏数据数据。怎么办?时间比较晚将近11点了,这会儿处理数据有风险,先写SQL 明早跟客户和测试沟通再处理数据,必须等客户同意删除数据。

时间来到第二天早上,呵、代码还没写两行,同事提交了一条"SQL 审批"删除 mongodb 数据,因为在测试环境验证了直接点同意;接着提交了第二条删除 ES 数据审批,没收到审批通知,我直接帮忙提交。

我点点点,一路执行畅通无阻,原本以为客户恢复正常了,一切都在掌握中。没想到我还是太天真了,紧接着噩耗来了,售后工单群直接炸了,客户一顿喷。

what ???我泪崩啊此刻心情。。。如下表情包

工作了七八年,没想到删表在我身上发生了,这是多低级错误一口老血喷出。

问题定位

日志系统采集错误日志,下面这条日志非常频繁。

python 复制代码
Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed

一开始并没有怀疑索引被删除,因为业务持续有数据产生。向 Es 写入数据时,如果指定的索引不存在,Es 会自动创建该索引,检查了发现 index 还在。

另外对同事写的删除数据脚本非常信任,怀疑是数据损坏了。赶紧写个脚本检索数据发现测试公司数据没了,应该是索引被删除了。

排查已执行删除数据脚本,发现下图资源缺了一部分被转化成了删除索引的脚本。

转换后 CRUL 如下:

css 复制代码
curl --location --request DELETE 'http://localhhost:9200/index_test' \
--header 'Content-Type: application/json' \
--data '{
  "query": {
    "bool": {
      "must": [
        {
          "terms": {
            "id": ["your_value"]
          }
        }
      ]
    }
  }
}'

实锤了不是数据问题,Index 被我们执行的脚本删了。

正确的删除姿势应该是

bash 复制代码
POST /your_index_name/_delete_by_query
{
  "query": {
    "match": {
      "your_field": "your_value"
    }
  }
}

bash 复制代码
DELETE /your_index_name/_doc/your_document_id

解决方案

怎么办?同事有点慌,删除数据库没想到在发生在自己身上。经过和运维同事沟通,索引和数据已删除没办法恢复,只能另想办法。

刚好又是早高峰必须抓紧决策方案,多浪费一分钟客户就多承担一分钟代价。

第一步 创建索引

果断决策先创建索引,列表报错客户根本没法使用,系统都进不到,另外依赖的系统还不少这部分流量怎们办?创建索引只能停服,停服影响范围?最终决策先停服务创建索引,保证客户增量业务正常「后来证实方案是正确的,增量业务正常了一部分客户问题解决了」。

出现问题--->定位.....-->保证增量数据正常,耗时26分钟。

第二步 存量数据修复方案

先确定是否有完整数据源用于恢复Es数据,还好mongodb 主库有全量数据,简直救我老命。es 可以理解为读模型用于检索业务。存量数据尤其是最近几周产生数据才是最重要的,客户非常着急,如果没有恢复数据客户工作展开不了。

确认有可靠数据源,接下就是数据同步方案了,现写脚本肯定赶不上,脚本开发+自测+测试验证+上线没有1小时搞不定。经过讨论有一个链路可行,当前业务具备一个能力从kafka消费数据写入Es,只要把数据写入kafka,就可以自动消费数据同步es。

数据怎么写入 Kafka?最容易想到的方案是采集mongodb 日志 oplog 写入Kafka,我们有现成的工具。整个链路可以打通了,如下图

第三步 优先处理头部客户

待同步Es数据量大,我们直接将全量数据导入Kafka,本以为等数据同步完就好了。经过验证数据同步至少3小时「最终同步完时间差异不大,预估是准确的」。

刚同步几分钟很多头部客户闹过来了。肯定不能一把抓,租户也有优先级,故障对于头部租户影响最大,头部爸爸服务不好你可能就下岗了。

先把Kafka数据丢弃,最常见是拨偏移量,但要停服放弃了;同事建议新建topic改配置重启服务「采用了这种方案」。收集头部客户将头部客户数据投递Kafka中。

确认头部客户方案简单。

1、 联系售后,遇到故障头部租户比你还着急。

2、 统计数据,不展开细说懂得都懂。

第四步 通道隔离

消费Kafka写入Es是线上逻辑,用该通道同步存量数据线上数据实时性保障不了,增量数据受影响。

经过分析和讨论,可以紧急开辟一条通道和现通道并存。紧急优化代码新增通道,同步存量数据与线上通道隔离。

经过几小时同步,数同步完成。

总结

1、 线上数据删除一定要非常谨慎,脚本或SQL开发者一定要自测到位「自测环境和线上环境保持一致,这次故障就是因为操作线上用内部工具和线下是有差异的」,对于审批者是最后的守门员,一定要自己把好关,可以慢但一定要严谨。

2、 故障已发生没办法避免,一定要冷静应对,思考对策。严重故障就是在抢时间一定要快。

3、 问题处理不要胡乱抓,优先处理头部客户。头部客户才是受影响最广、最严重、最需要处理的。

4、 完成止血后,应该思考更完善方案加速问题处理,减少腰部客户和尾部客户损失。比如我列的通道隔离方案。

5、 客户选择你是对你的信任。系统稳定性、易用性、客户数据安全性一定要得到保障,才是客户留下的根本。每一步操作对客户有影响都要慎重、慎重。

真是惊心动魄一天,经过几小时奋斗,数据问题已经恢复了。也给我们留下了深刻印象,问题本可以避免的,真是血淋淋教训啊。

相关推荐
sunbin6 分钟前
稀土掘金我要吐槽你
后端
程序员鱼皮2 小时前
我代表编程导航,向大家道歉!
前端·后端·程序员
zjjuejin2 小时前
Maven 生命周期与插件机制
后端·maven
阿杆2 小时前
为什么我建议你把自建 Redis 迁移到云上进行托管
redis·后端
Java水解2 小时前
go语言教程(全网最全,持续更新补全)
后端·go
bobz9652 小时前
QEMU 使用 DPDK 时候在 libvirt xml 中设置 sock 的目的
后端
thinktik3 小时前
AWS EKS 计算资源自动扩缩之按需申请Fargate[AWS 中国宁夏区]
后端·aws
thinktik3 小时前
AWS EKS 实现底层EC2计算资源的自动扩缩[AWS 中国宁夏区]
后端·aws
uhakadotcom3 小时前
什么是OpenTelemetry?
后端·面试·github
知其然亦知其所以然3 小时前
MySQL 社招必考题:如何优化特定类型的查询语句?
后端·mysql·面试