MongoDB使用教程系列文章--Driver原理(初始化)

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介:

前言

Driver是MongoDB非常重要的组成部分,通过不同的配置实现Secondary访问;读写分离,动态感知集群容灾切换等功能。MongoDB目前已经覆盖了大部分的开发语言,常见的JAVA到Go,可以参考官方连接MongoDB Drivers。这篇文章我们以Java版本为例介绍MongoDB的Drivers实现逻辑和协议,选择Java的原因为语言阅读门槛低,配合IDE,进行DEBUG追踪也非常容易,其次Java版本实现的功能非常完善。主要讲解的是ReplicaSet模式,因为Shard模式有mongos作为代理,没有充分体现Driver的路由逻辑。

本篇讲解了以下三个部分:

  • Driver初始化
  • Driver请求路由
  • Driver容灾处理

Driver初始化

配置启动参数DEMO

首先来看下Java初始话配置Demo:

 public static MongoClient createMongoDBClient() {
        // 构建Seed列表
        List<ServerAddress> seedList = new ArrayList<ServerAddress>();
        seedList.add(seed1);
        seedList.add(seed2);

        // 构建鉴权信息
        List<MongoCredential> credentials = new ArrayList<MongoCredential>();
        credentials.add(MongoCredential.createScramSha1Credential(username,
                DEFAULT_DB, password.toCharArray()));

        // 构建操作选项,requiredReplicaSetName属性外的选项根据自己的实际需求配置,默认参数满足大多数场景
        MongoClientOptions options = MongoClientOptions.builder()
                .requiredReplicaSetName(ReplSetName).socketTimeout(2000)
                .connectionsPerHost(1).build();
        return new MongoClient(seedList, credentials, options);
    }

还有另外一种通过URI初始化的方法:

public static MongoClient createMongoDBClientWithURI() {
        //另一种通过URI初始化
        //mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
        MongoClientURI connectionString = new MongoClientURI("mongodb://" + username + ":" + password + "@" + 
                                                             seed1 + "," + seed2 + "/" + 
                                                             DEFAULT_DB + 
                                                             "?replicaSet=" + ReplSetName);
        return new MongoClient(connectionString);
    }

两种方式的实现原理么有本质区别,Driver会将URI拆解为第一种的参数设置方式。

  • URI方式的有点是在复杂的系统中更通用,不同编程语言系统可以共享一套初始化配置;如果有多套异构的系统访问MongoDB,建议采用URI的方式。
  • Builder方式更灵活,对参数的设置非常细,并且代码清晰易读。

设置Seed地址

仔细的读者会注意到,Address地址变量叫做Seed,而不是MongoDB集群上的Primary,Secondary,或者其他名称。Seed是MongoDB访问地址的一种抽象概念,可以是MongoDB集群中的任意一个节点,如果是ShardCluster模式,则应该是Mongos地址。这样的好处是使用者不需要关系集群的状态改变,更不用随着集群状态改变而修改配置。比如,增加了一个新的节点,再或者发生了Primary与Secondary之间的角色切换,但Seed却保持不变,只要是集群中的任意地址即可。然而Driver在处理请求时是需要明确Primary,Secondary等角色的地址关系。

构造ServerMonitor线程

所谓的初始化,就是对集群状态的第一次获取,并且构建Driver内部使用的ServerMonitor线程,集群中的每个节点,都对应有一个ServerMonitor。初始状态下会以Seed为起点开始,ServerMonitor主要有几下个动作:

首先检车连接状态,如果是不可用的,需要重新建立链接,并执行Action A动作:

Action A:ConnectionOpen,每个连接的建立好都会执行以下的请求

  1. ismaster 这里的作用相当于Ping一下,在这个Action中没有特别的作用
  2. buildinfo 获取Server的版本信息,目的是做版本之间的兼容性
  3. auth 如果配置有鉴权属性,会执行此步骤,目前默认的是SASL,可以参考RFC,SCRAM方式一般需要三次的RPC交互。
  4. getlasterror 确定上面的请求没有出错,整个Action结束

    连接Ready后,开始心跳,并且间隔性的检查,默认每10秒钟,可配置,但最小不能低于500毫秒

Action B:LookupServerDescription

  1. ismaster 与Action A的命令一样,但这里获取到的信息非常重要
  2. 检查上一步刚刚获得的Server Description与之前的是否一致,如果没有发生任何改变,状态稳定,则该轮心跳检查结束。不一致,则产生changeEven事件,调用Acton C。

如果有必要,则继续执行OnChanged Listener:

Action C:Server Description OnChanged

  1. 更新Server Hosts列表,如果列表中之间不存在该地址,则新创建连接,以新地址构造ServerMonitor线程
  2. 如果当前节点是Primary,还要更新ElectionId等字段

在Action C动作结束后,每个Server都产生了一个Server Montior线程,并且Driver也同步到了集群状态,Primary地址,ElectionId等信息。一旦集群信息发生改变,心跳线程也会随时发现并做出相应的修改。

MongoDB_Driver_init

连接池ConnectionPool

ServerMonitor是独立的线程,只保证心跳检查,不处理真正的用户请求。用户的请求是通过其他的连接完成,那对连接的管理是有个套ConnectionPool机制,每个连接有一套独立的ConnectionPool。初始化后ConnectionPool是空的,等请求需要时会在建立连接。

请求线程从Pool中拿到Connection后,会在请求线程里处理请求,结束后再放回给ConnectionPool。不同的实现语言,这里处理的逻辑并不一样,不属于MongoDB约定的协议范围内。

isMaster命令:

可以参考官方文档,isMaster,在MongoShell中执行会得到以下结果,非常重要的是ismaster和hosts字段,这两个字段完整的描述了集群的状态信息。Action B.2的判断,依赖ismaster的是否是true.

{
    "setName" : "rs0",
    "setVersion" : 3,
    "ismaster" : true,
    "secondary" : false,
    "hosts" : [
        "10.1.2.123:12300",
        "10.1.2.124:12300"
    ],
    "primary" : "10.1.2.123:12300",
    "me" : "10.1.2.123:12300",
    "electionId" : ObjectId("569dfe3aba498a31641f3630"),
    "maxBsonObjectSize" : 16777216,
    "maxMessageSizeBytes" : 48000000,
    "maxWriteBatchSize" : 1000,
    "localTime" : ISODate("2016-01-20T04:54:20.768Z"),
    "maxWireVersion" : 3,
    "minWireVersion" : 0,
    "ok" : 1
}

从整个流程上可以看到,ismaster命令存在冗余,一个连接的初始化逻辑,至少需要发送2次,并且对同一个Server,不同的连接还是要发送,很多情况不是必要的,可以简化,提高连接建立的速度。

MongoDB Driver初始化总结

通过对MongoDB Driver For Java的分析,我们已经很清楚了初始化的行为动作,包括平时运行时的大概情况,其他语言的实现也大同小异,跑不出这个流程。希望对读者日后处理客户端初始化问题时有所帮助。

MongoDB_Driver_UML

了解原理后我们回头来思考下,怎么使用才是最佳实践,主要几点:

  1. 从整个流程上看,MongoDB Driver初始化的过程很‘重’,要交互很多次,尤其是使用PHP的同学注意了,不建议采用短连接的方式,请将MongoDB的连接持久化下来。
  2. 每个Driver都至少会有一个Monitor连接,而且是不会回收的。所以,规划连接数时,需要关注到这点。
  3. 提高请求线程并发量的同时,尝试同步提高连接池上限,对性能会有一定帮助。但请注意,不是越多越好,过多的线程会导致线程调度消耗过多的资源。而且请配置连接的IDLE time,让其自动回收长期不用的连接,避免连接泄漏。
  4. 最重要的一点,学会用isMaster命令排查问题,Driver请求无法访问时,尝试在Mongo Shell中执行isMaster,确保返回的集群信息都是正确的。并且isMaster是不需要鉴权的,所以,保护好你的MongoDB实例,不要出现的公网上。
  5. 配置多个Seed地址是,避免其中一个不可用。
  6. ......
 待续,Driver请求路由
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
2月前
|
存储 缓存 NoSQL
MongoDB内部的存储原理
这篇文章详细介绍了MongoDB的内部存储原理,包括存储引擎WiredTiger的架构、btree与b+tree的比较、cache机制、page结构、写操作流程、checkpoint和WAL日志,以及分布式存储的架构。
67 1
MongoDB内部的存储原理
|
5月前
|
存储 监控 NoSQL
MongoDB索引解析:工作原理、类型选择及优化策略
MongoDB索引解析:工作原理、类型选择及优化策略
|
1月前
|
存储 NoSQL MongoDB
MongoDB入门级别教程全(Windows版,保姆级教程)
一份全面的MongoDB入门级教程,包括在Windows系统上安装MongoDB、使用MongoDB Shell和Compass GUI进行数据库操作,以及MongoDB的基本数据类型和查询技巧。
66 2
MongoDB入门级别教程全(Windows版,保姆级教程)
|
1月前
|
存储 JSON NoSQL
MongoDB Compass 的教程
这篇文章提供了MongoDB Compass的基本使用教程,包括如何建立数据库连接、创建和删除数据库、插入和修改文档数据,以及执行聚合查询来分析和排序数据。
173 0
MongoDB Compass 的教程
|
5月前
|
NoSQL 前端开发 MongoDB
[保姆级教程]Windows安装MongoDB教程
【6月更文挑战第4天】该内容是关于MongoDB的安装包下载及安装步骤指南。首先,访问网址 &lt;a href=&quot;https://www.mongodb.com/try&quot; target=&quot;_blank&quot;&gt;https://www.mongodb.com/try&lt;/a&gt; 进入官网,选择MongoDB Community Edition(社区版)。接着,挑选合适的版本和系统平台,推荐下载zip压缩包。下载后,进行安装,依次点击“Next”同意协议,选择自定义安装路径,然后继续安装直至完成。
599 0
|
30天前
|
SQL NoSQL MongoDB
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
41 0
|
1月前
|
存储 JSON NoSQL
MongoDB 教程
10月更文挑战第9天
34 0
|
3月前
|
JavaScript NoSQL 前端开发
|
3月前
|
人工智能 NoSQL Go
Go MongoDB Driver 实例
Go MongoDB Driver 实例
23 1
|
3月前
|
人工智能 JSON NoSQL
Go MongoDB Driver 中的 A D M E 类型是什么
Go MongoDB Driver 中的 A D M E 类型是什么
39 1

相关产品

  • 云数据库 MongoDB 版