RDS/MongoDB使用注意事项

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 MongoDB,通用型 2核4GB
简介: 阿里云RDS/MongoDB提供了开箱即用的高可用服务,站在开发者的视角在使用中应当注意哪些事项呢?本文针对连接池管理、副本集配置和常用连接参数等知识点进行了总结。

一、背景知识


1、链接类型

A、短链接:一般都是PHP环境,因为PHP的框架决定了PHP短链接的特性,并且链接数的需求一般是在1000-3000左右,具体多少还要根据业务部署的PHP数量来计算。
并且MongoDB开源版本在短链接Auth处理上并不优雅,会消耗非常多的CPU资源,3000链接即可跑满24Core的CPU。
Facebook也有同样的问题,所以他们用go语言自行开发了一套Proxy代理,来解决对MongoDB的短链接请求问题,但这毕竟带来部署成本和兼容性问题。

B、长链接:比较健康合理的使用方式,但是也要正确的配置客户端,相关的参数为&maxPoolSize=xx 在ConnectionURI上追加上去即可,否则默认每个客户端就是高出100来个,平白的浪费资源
链接数的上限需要综合考虑性能,稳定性,业务需求。多方面去考虑,缺一不可。

2、连接消耗资源

连接是要消耗资源的,而且消耗的并不少。
A、内存:以MongoDB为例,每个线程都要分配1MB的栈内存出来。1000个连接,就耗费1G内存,不管是否活跃连接。
B、文件句柄:每个连接都要打开一个文件句柄,当然从成本上讲,这个消耗相对内存是小了很多。但换个角度,文件句柄也被其他模块消耗着,比如WT存储引擎,就需要消耗大量的文件句柄。

3、限制连接数目
Mongod 的服务模型是每个网络连接由一个单独的线程来处理,每个线程配置了1MB 的栈空间,当网络连接数太多时,过多的线程会导致上下文切换开销变大,同时内存开销也会上涨。

是否真的需要这么多的链接?
举例:一般的业务场景下请求压力在1000QPS左右,按照每个请求50ms计算,最多也就需要1000/(1000/50)==50个链接即可满足需求,并且是整个系统50个链接即可。

二、连接池管理

1、正确的连接池配置方式:

MongoDB 各个语言的Driver 基本都会封装包含一个 MongoClient 的对象(不同语言的 Driver 名字可能稍有不同),通常应用在使用时通过 MongoDB connection string URI 来构造一个全局的 MongoClient,然后在后续的请求中使用该全局对象来发送请求给Mongod。
应用使用的方式大致类似于
// 通常的用法

// global MongoClient object
mongoClient = new MongoClient("mongodb://root:****@host1:port1,host2:port2/admin?replicaSet=repl00&maxPoolSize=100");

// request1
db1 = mongoClient.getDatabase("db1");
coll1 = db1.getCollection("coll1");
coll1.find({...})

// request2
db2 = mongoClient.getDatabase("db2");
coll2 = db2.getCollection("coll2");
coll2.update({...})

// requestN
...
通常每个 MongoClient 会包含一个连接池,默认大小为100,也可以在构造 MongoClient 的时候通过 maxPoolSize 选项来指定。

2、错误的连接池配置方式

一种典型的错误使用方式是,用户为每个请求都构造一个 MongoClient,请求结束释放 MongoClient(或根本没释放),这样做问题是请求模型从长连接变成了短连接,每次短连接
都会增加『建立 tcp 连接 + mongodb鉴权』的开销,并且并发的请求数会受限于连接数限制,极大的影响性能;另外如果 MongoClient 忘记释放,会导致MongoClient 连接池里连接一直保持着,最终耗光所有的可用连接。
// 错误的用法
// request1
mongoClient = new MongoClient("mongodb://root:****@host1:port1,host2:port2/admin?replicaSet=repl00&maxPoolSize=100");
db1 = mongoClient.getDatabase("db1");
coll1 = db1.getCollection("coll1");
coll1.find({...});
mongoClient.close();


// request2
mongoClient = new MongoClient("mongodb://root:****@host1:port1,host2:port2/admin?replicaSet=repl00&maxPoolSize=100");
db2 = mongoClient.getDatabase("db2");
coll2 = db2.getCollection("coll2");
coll2.update({...});
MongoClient.close()

// requestN
...

3、选择合适大小的连接池

通常 MongoClient 使用默认100的连接池(具体默认值以 Driver 的文档为准)都没问题,当访问同一个 Mongod 的源比较多时,则需要合理的规划连接池大小。
举个例子,Mongod 的连接数限制为2000,应用业务上有40个服务进程可能同时访问 这个Mongod,这时每个进程里的 MongoClient 的连接数则应该限制在 2000 / 40 = 50 以下。
(连接复制集时,MongoClient 还要跟复制集的每个成员建立一条连接,用于监控复制集后端角色的变化情况)

三、副本集配置

1、MongoDB复制集(Replica Set)

MongoDB复制集里Primary节点是不固定的,当遇到复制集轮转升级、Primary宕机、网络分区等场景时,复制集可能会选举出一个新的Primary,而原来的Primary则会降级为Secondary,即发生主备切换。
总而言之,MongoDB复制集里Primary节点是不固定的。
当连接复制集时,如果直接指定Primary的地址来连接,当时可能可以正确读写数据的,但一旦复制集发生主备切换,连接的Primary会降级为Secondary,将无法继续执行写操作,将严重影响生产服务。
所以生产环境千万不要直连Primary。

2、正确连接复制集的姿势

要正确连接复制集,需要先了解下MongoDB的Connection String URI,所有官方的driver都支持以Connection String的方式来连接MongoDB。

下面就是Connection String包含的主要内容
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
mongodb:// 前缀,代表这是一个Connection String
username:password@ 如果启用了鉴权,需要指定用户密码
hostX:portX 复制集成员的ip:port信息,多个成员以逗号分割
/database 鉴权时,用户帐号所属的数据库
?options 指定额外的连接选项

-- 例如通过java来连接:
MongoClientURI connectionString = new MongoClientURI("mongodb://root:****@dds-xxxxxxxxxxxxxxx.mongodb.rds.aliyuncs.com:3717,dds-xxxxxxxxxxxx.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-677201"); // ****替换为root密码
MongoClient client = new MongoClient(connectionString);
MongoDatabase database = client.getDatabase("mydb");
MongoCollection<Document> collection = database.getCollection("mycoll");

 

-- spring boot 
spring.data.mongodb.uri = mongodb://xxxxx:xxxxxxxx@dds-xxxxxxxxxxxxxx.mongodb.rds.aliyuncs.com:3717,dds-xxxxxxxxxxxxxxx.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-2293069
spring.data.mongodb.database = xxxxxxxxxxx

3、常用连接参数:

如何实现读写分离?
在options里添加readPreference=secondaryPreferred即可实现,读请求优先到Secondary节点,从而实现读写分离的功能。
mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&readPreference=secondaryPreferred

如何限制连接数?
mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&maxPoolSize=50
-- The maximum number of connections in the connection pool. The default value is 100.

如何保证数据写入到大多数节点后才返回?
在options里添加w= majority即可保证写请求成功写入大多数节点才向客户端确认。
mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&maxPoolSize=50&w=majority


如何指定连接超时时间?
mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=10000&socketTimeoutMS=5000

-- connectTimeoutMS:建立新连接超时时间(Only used for new connections), 默认无限制(可以打开连接的时间。)
The time in milliseconds to attempt a connection before timing out. The default is never to timeout。

-- socketTimeoutMS:socket通讯超时时间,默认无限制(发送和接受sockets的时间。)
The time in milliseconds to attempt a send or receive on a socket before the attempt times out. The default is never to timeout。

相关实践学习
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
目录
相关文章
|
7月前
|
NoSQL 关系型数据库 分布式数据库
RDS、PolarDB、Redis、MongoDB、DAS中执行一条修改语句为啥要开binlog呢
RDS、PolarDB、Redis、MongoDB、DAS中执行一条修改语句为啥要开binlog呢
113 1
|
11月前
|
存储 NoSQL Oracle
「数据库选型」卫报从MongoDB迁移到Amazon RDS上的PostgreSQL
「数据库选型」卫报从MongoDB迁移到Amazon RDS上的PostgreSQL
|
NoSQL 关系型数据库 MySQL
DLA支持分析MongoDB/RDS只读实例
在对Mysql,MongoDB等数据库系统进行分析时,经常面临的一个问题是在进行分析查询时如何避免对实时业务产生影响,也就是OLAP负载和OLTP负载隔离的问题。针对这个问题,阿里云数据湖团队一直在努力优化,提供满足不同场景的解决方案。
719 0
DLA支持分析MongoDB/RDS只读实例
|
弹性计算 NoSQL 关系型数据库
ecs与数据库(rds,redis,mongodb,memcached)连通性判断流程图
由于文档https://yq.aliyun.com/articles/164796内容较多,不方便查看,可以参考流程图来初步判断连通性是否正常
ecs与数据库(rds,redis,mongodb,memcached)连通性判断流程图
|
监控 安全 关系型数据库
性能测试:自建数据库对比RDS中应当注意的地方(适用于MySQL,SQL SERVER,MongoDB)
常常很多用户对比测试自建数据库和RDS的性能差异,其测试结果往往是RDS不如ECS自建,用户往往怀疑难道我花了那么多的钱买的RDS难道还不如自己在ECS上搭建吗?
16825 0
|
NoSQL 数据库 数据安全/隐私保护
mongodb一些使用技巧或注意事项记录
1、有的时候需要删除指定字段那一列,使用update操作。例如要删除name这一列: query  json: {"name":{$exists:true}} update json: {$unset:{"name":""}} 2、数据导出,在mongodb的bin目录执行mongoexport命令并设定相关的参数,例如: ./mongoexport -h 1
2236 0
|
1天前
|
NoSQL MongoDB 数据库
MongoDB数据恢复—MongoDB数据库文件被破坏的数据恢复案例
服务器数据恢复环境: 一台Windows Server操作系统服务器,服务器上部署MongoDB数据库。 MongoDB数据库故障&检测: 工作人员在未关闭MongoDB数据库服务的情况下,将数据库文件拷贝到其他分区。拷贝完成后将原MongoDB数据库所在分区进行了格式化操作,然后将数据库文件拷回原分区,重新启动MongoDB服务,服务无法启动。
|
5天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
50 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
1月前
|
NoSQL 网络协议 MongoDB
Windows公网远程连接MongoDB数据库【无公网IP】
Windows公网远程连接MongoDB数据库【无公网IP】