巧用 maxTimeMS 服务端超时,避免承载亿级用户的腾讯云数据库MongoDB服务雪崩

​腾讯云数据库MongoDB作为一款基于开源社区MongoDB版本的文档数据库产品,其承载着公司内外包括微信、看点、QQ音乐在内的亿级用户重量级APP产品。在某些场景的使用过程中,用户在客户端请求超时后会不断重试,可能导致服务端大量请求积压,出现恶性循环甚至导致服务雪崩。一般遇到这种情况,后台会自动检测并做服务降级,主动拒绝一部分用户请求,或者重启后端服务等举措来应对。但是这些措施对业务有损,或者不可自行恢复。

本文围绕 MongoDB 原生 maxTimeMS 特性和腾讯云MongoDB的优化,并结合 4.0 版本代码,详细阐述如何巧用 maxTimeMS 服务端超时,来避免服务端请求积压导致雪崩的情形。

背景

业务方在腾讯云MongoDB运营过程中,曾有业务集群出现过:慢请求 -> 客户端断开重试 -> 服务端累积的请求越来越多 -> 服务雪崩 -> 人工重启解决的问题。

过去,为了防止服务雪崩,腾讯云MongoDB应对的解决方案是:在内核中实现了连接状态检测、自适应限流等功能进行过载保护,并开发了外围工具 kill 长时间运行的请求等。但是过载保护本质上会进行服务降级,对业务还是会产生一定影响,而外围工具处理起来也不够及时,甚至可能在节点 hang 住时无法工作,以上解决举措都存在着一定程度的弊端。

为了更好地避免服务雪崩,腾讯云MongoDB建议设置服务端超时,并和客户端超时保持一致。这样在客户端出现超时后,服务端也立刻终止这些“无意义”请求的执行。通过避免服务端资源的无效占用,极大地降低客户端不断重试导致服务雪崩的概率。

MongoDB原生服务端超时原理

当一个用户请求到达 mongos 或者 mongod 时,会生成一个对应的 OperationContext 对象,来记录这个请求从开始到结束期间的完整上下文信息。上下文信息中就包含了后面要介绍的“时间信息”:起始时间,已执行时间,超时时间,以及是否是 kill 状态等。相关成员和接口如下图所示:

其中 checkForInterrupt() 接口的作用就是检测请求是否应该终止,需满足以下 3 个条件之一:

1.实例处于 shutdown 状态;

2.用户使用 killOp 命令,调用 markKilled() 接口,将 OperationContext 标记为了终止状态;

3.用户通过 maxTimeMS 参数给 OperationContext 配置了超时 Deadline,然后检测到 hasDeadlineExpired() 为 true;

一个请求在执行过程中会多次调用 checkForInterrupt() 检测自己是否超时,比如在获取Global ticket,获取资源锁,yield,内部迭代重试等阶段会主动检测并超时退出。

备注1:原生 MongoDB 在 3.7.3 版本通过 SERVER-33473 (https://jira.mongodb.org/browse/SERVER-33473才支持获取 Global Ticket 时能够主动超时和打断,因此更低版本在 qr/qw 较大,请求排队比较严重时无法及时超时退出;而且在 3.7.3 版本通过 SERVER-32638  (https://jira.mongodb.org/browse/SERVER-32638才支持获取资源锁时主动超时,因此更低版本在获取互斥锁卡住时也无法及时超时退出。

因此,为了有更好的体验,强烈建议升级到 4.0 或更高版本。

<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值