MongoDB 复制集如何实现读写分离

MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用。但需要注意的时,连接副本集的姿势如果不对,服务高可用将不复存在。

使用前须知

MongoDB复制集里Primary节点是不固定的。当遇到复制集轮转升级、Primary 宕机、网络分区等场景时,复制集可能会选举出一个新的Primary,而原来的Primary则会降级为Secondary,即发生主备切换。总而言之,MongoDB 复制集里 Primary 节点是不固定的。

当连接复制集时,如果直接指定Primary的地址来连接,当时可能可以正确读写数据,但一旦复制集发生主备切换,连接的Primary会降级为Secondary,将无法继续执行写操作,这将严重影响到用户的线上服务。所以生产环境千万不要直连Primary,那么到底该如何连接复制集?

正确连接复制集

要正确连接复制集,需要先了解下MongoDB的 Connection String URI,例如:

mongodb://username:password@10.173.33.24:27017/admin?replicaSet=mg163-1508&key=value

具体如何获取MongoDB实例连接信息,请查看获取连接信息

MongoDB Driver 通过 URI 来连接 MongoDB 服务,URI 格式适用于所有官方提供的各种语言驱动,包括 Java、Python 等,URI 格式如上所示

说明:

  • username 和 password 为在 MongoDB 上创建的账号和密码;
  • 10.173.33.24:27017 表示提供给驱动连接 MongoDB 的种子,网易云 MongoDB 提供实例浮动 IP 作为种子;
  • /admin 表示进行该账户鉴权的数据库,MongoDB 的鉴权数据库必须是创建该账号时所在的数据库;
  • 网易云 MongoDB 服务统一在 admin 库上为用户创建账号;
  • replicaSet 为 MongoDB 实例的复制集名称;
  • &号后的 key 和 value 对表示其他可设置的连接参数,可指定多个,如下:
  • 实现读写分离:在options里添加readPreference=secondaryPreferred读请求优先到Secondary节点,从而实现读写分离的功能。更多读选项请参考Read preferences
  • 限制连接数:在options里添加maxPoolSize=xx即可将客户端连接池限制在xx以内。
  • 设置数据写入到大多数节点后返回客户端确认:在options里添加w= majority即可保证写请求成功写入大多数节点才向客户端确认,更多写选项参考Write Concern

以连接网易云 MongoDB为例,当用户购买网易云MongoDB复制集时,会得到复制集的名称以及复制集成员的地址信息。如下图所示:

Mongo DB Connection

例如通过Java来连接网易云 MongoDB(配置了读写分离参数):

public static String mongoConnStr = "10.173.33.24:27017";
public static String mongoUser = "root";
public static String mongoPasswd = "password"; //这里修改为对应密码
public static String replSet = "mg163-1508";
public static String options = "&readPreference=secondaryPreferred" //实现读写分离
public static MongoClient mongoClient;

public static void mongoInit() {  
  String connectStr = "mongodb://" +  mongoUser + ":" + mongoPasswd + "@" + mongoConnStr + "/admin?replicaSet=" \
	+ replSet + options;
  try {
    MongoClientURI uri = new MongoClientURI(connectStr);
    MongoClientOptions.builder().cursorFinalizerEnabled(false);
    mongoClient = new MongoClient(uri);
  } catch (Exception e) {
    System.out.println("Start init MongoClient error: " + e.toString());
    if (mongoClient != null) {
      mongoClient.close();
    }
  }
 }

连接诊断方法

当程序遇到连接问题时,可以使用mongo shell 来快速诊断定位问题, 使用命令如下:

mongo --host 10.173.33.24:27017 --authenticationDatabase admin -u root -p

详细使用请参考 Mongo Shell 连接

输入正确密码,若可以正常登陆,可以反过来查看程序是否有问题。