记一次线上事故 -- lvs 宕机引起的血案

2016-02-01 18:09:12   最后更新: 2016-04-26 11:52:01   访问数量:1425




PHP -> mgw(美团基础架构组对 lvs 的封装)-> atlas(数据库中间件) -> DB

 

mgw 机器 2月1日 11:30 突然宕机,导致 PHP 端大量读超时(10 秒),加锁的语句没有解锁,导致其他语句无法获取锁造成死锁

 

然而,由于 rabbitmq 1.6.1 心跳设置的是 2 秒,两次(4 秒)检测不到心跳就会将消息重新发送给另一个 worker,所以在 PHP 读超时前,相同消息被 rabbitmq 转发到了另一个 worker,造成了雪崩效应

 

大量重复 SQL 被提交 DB 执行,select for update 语句造成死锁,因此要求 DBA kill 掉死锁连接,结果 DBA kill 掉了所有连接,造成订单丢失,mysql insert  操作即使没有显式开启事务,执行过程中也会开启一个小事务,在返回 ID 的时候,并不意味着执行成功,DBA kill 掉所有连接后,事务回滚,导致 2100 多个订单没有写入成功,但是 PHP 端返回了 orderid,流程继续执行,支付成功,用户却无法看到订单

事后根据 paylog 对这些订单进行了退款操作

 

  • rabbitmq 心跳设置大于 php 数据库读写超时/2
  • 设置两个延时队列,处理失败放入缓冲队列,缓冲队列没 10 秒处理一次,失败放入次级缓冲队列,1min 处理一次,失败退款
  • 指定应急预案,一旦出现问题,重启 atlas,事实上如果事故发生第一时间重启 atlas,php 脚本会立即返回订单创建失败,相应事务不会执行成功

 

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

 






技术帖      php      mysql      技术分享      rabbitmq      db      lvs      事故      case      casestudy      atlas     


京ICP备15018585号