简述
2020.01.21 2:00
做了一个索引优化。将3个索引优化为1个。只保留了一个{session_id, create_timestamp}索引,更到线上后未发现大的问题。
2020.01.24 1:00
发现数据库访问RTT不明原因地升高。触发了限流,部分用户不能登录。因为凌晨的访问量是平时的3-5倍。因为各方面指标都慢慢趋于正常。未做更多处理。
2020.01.24 16:00
午睡时想到凌晨的种种奇怪现象(另一个database的RTT也变高了)。
完全不相干的两个database。CPU没遇到瓶颈,只可能是磁盘IO了。一看磁盘IO吓一跳,居然是满的!(讶异于没有磁盘IO报警,也讶异于索引有不对的地方),mongotop一看。相关table的read/write 都在1Kms级别。
仔细地比较各个操作的rtt时间,发现msg表的update从更新前的1ms内,上涨到了6-7ms。msg表最慢的round trip,没有大的变化。看来是长尾效应导致的问题。
查看代码时发现,在设置消息已读时,正常情况下会在unread_sessions拿到该会话的一个未读create_timestamp,在设置后,会清理掉该create_timestamp。在设置一个无unread的会话时,拿不到时间戳,会向前检索一周的消息。从慢查询日志中发现,有update操作会遍历300多条记录。
之后的fix和更新就不谈了。
总结
任何线上问题的发生都是多个错误综合造成的。总结如下:
监控
- 磁盘IO报警没有生效。
- 应用层监控缺乏数据库的整体表现情况。除了关注最坏rtt, 特定接口的rtt,还要关注整体情况。最直观的就是mongotop,磁盘IO使用率,CPU使用率,网络IO使用率。
- 应监控慢查询的数量,达到一定阈值报警。
灰度
测试机器人和用户表现不一致。需要灰度机制发现问题。
敬畏心
做服务端要细心,动的时候就有点怂。动完应对线上情况做更多观测(当时觉得有任意索引BUG,都会导致整个数据库卡死,10亿规模的表)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。