线上环境又报:mongo can not add session to cache,有了之前的经验,这次排查和解决问题算是轻车熟路了。

日志!

直接登录到线上环境,查看mongo集群日志,发现此次问题和之前遇到的不太一样:

1
2
3
24737:2021-08-10T15:34:41.196+0800 I CONTROL  [LogicalSessionCacheRefresh] Failed to refresh
session cache: WriteConcernFailed: waiting for replication timed out; Error details: { wtimeout:
true } at data_set1

看这个样子,应该是内存中的activeSessionsCount无法写入config.system.sessions表中。

集群状态

运行命令查看当前集群节点状态:mongostat --discover --interactive --host 127.0.0.1:27010

image-20210817163327633

果然,data_set1的一个副节点挂掉了。

但是,主节点仍然在运行,正常情况下是可以写入数据的呀。先把这个挂掉的节点恢复再说!

writeConcern

接下来,就看一下mongo集群是怎样把activeSessionsCount写入数据库的,继续查看日志,果然发现了端倪:

image-20210817171235537

正常情况下,对system.sessions表的写入操作有writeConcern: { w: "majority", wtimeout: 15000 }这样的配置。

那结合我们线上环境集群节点副本集的配置 Primary-Secondary-Secondary (P-S-S)模式,在挂掉一个节点之后,即使主节点仍然正常运行,w: "majority"有这样写入配置的操作也是无法成功的。

mongodb官方文档中有描述:

Requests acknowledgment that write operations have propagated to the calculated majority of the data-bearing voting members (i.e. primary and secondaries with members[n\].votes greater than 0).

For example, consider a replica set with 3 voting members, Primary-Secondary-Secondary (P-S-S). For this replica set, calculated majority is two, and the write must propagate to the primary and one secondary to acknowledge the write concern to the client.

也就是说,对于我们线上的副本集,必须保证主、副节点都正常运行,才可能达到 w: "majority"的要求。

小结

此次问题说明一些问题:

  1. 当前我们对线上mongo集群的监控不足,副本集副节点挂掉较长一段(activeSessionsCount高达40多万)时间直到线上服务报错后才发现;
  2. 对mongodb的writeConcernreadConcern研究不深入,对当前的集群部署模式研究不够。

后续需要继续完善对线上环境的监控和预警,深入研究mongodb本身。