MongoDB开发系列-复制集对程序开发的影响
本篇文章主要从以下几个方面说明复制集架构对程序开发的影响
笔者把基于MongoDb的应用开发分为软件运维和 软件开发两个阶段
本篇会侧重后一阶段的实践经验分享
- 理解复制集与主从结构
- 关注数据库连接字符串
复制集的基本概念
谈到复制集,它是副本的集合,分布式系统的基本属性之一。
副本(Replica)
副本是分布式系统最常见的概念之一,指分布式系统对数据和服务提供的一种冗余方式。在常见的分布式系统中,为了对外提供高可用的服务,我们往往会对数据和服务进行副本处理。有副本的概念,就会关联到副本数据一致性问题。
MongoDb环境下,我们很容易从公开资料查询到复制集的基本你含义
MongoDB 复制(副本集)MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许您从硬件故障和服务中断中恢复数据
副本集角色
MongoDB副本集是一组mongod进程的集合,它通过一系列机制实现了高可用。
mongod is the primary daemon process for the MongoDB system. It handles data requests, manages data access, and performs background management operations.
副本集角色主要包括主节点,从节点,和仲裁节点。 主节点负责所有的写操作。
复制集与主从结构的关系
两者属于不同的MongoDb数据库结构,主从结构已经不被官方推荐
Deprecated since version 3.6: MongoDB 3.6 deprecates the use of
master-slave replication.Master-slave replication has been deprecated
for components of sharded clusters since MongoDB 3.2.
主从结构与复制集最主要的区别是前者有真正的主服务器的概念,复制集没有主服务器的概念,通过选举选出主要的主节点Primary
Do not run an arbiter on systems that also host the primary or the secondary members of the replica set
仲裁者一定要部署在独立的服务器上,避免与主节点和复制节点部署在一起
传统的主从部署
复制集
这是Mongo官方更推荐的部署结构
复制集
关注数据库连接字符串
复制集属于MongoDb高可用架构的一种部署方式,对于使用数据库的应用者来说应该是极度透明的,内部主从实例切换应该做到无感切换,也就是说应用并不关心具体的一次数据库操作,是由哪个实例来处理的。
我们可以在程序中指定如何连接复制集,正确的连接方式可以避免当主节点宕机或者故障时,应用程序无感知正常切换,借用网络的一张图来说明
这张图的左边部分实际上是有问题的,直连一个实例,并且标明Primary,对于连接Db数据库的Driver来说,它应该不用关心哪个实例是主,并且哪个实例是主也是会变化的。
试想运维给到开发的数据库连接串是一组配置,那我们如何集成到应用程序中?
基础设置
对于PHP应用来讲,框架使用YII2,驱动使用yii2-mongodb
https://www.yiiframework.com/...
Github地址
https://github.com/yiisoft/yi...
- 安装
Either run php composer.phar require --prefer-dist yiisoft/yii2-mongodb or add "yiisoft/yii2-mongodb": "~2.1.0"
- 连接字符串
直连方式
return [ 'class' => '\yii\mongodb\Connection', 'dsn' => 'mongodb://username:[email protected]:10000/databasename', 'options'=>[ 'socketTimeoutMS' => 1000 ] ];
复制集连接
return [ 'class' => '\yii\mongodb\Connection', 'dsn' => 'mongodb://user:pqssword@s1._test.mongodb.domain.cn:30000,s2.mongodb.domain.cn:30000,s3._test.mongodb.domain.cn:30000/databasename', ];
问题来了
1 应该都连接,还是只连接一台数据库实例即可?
生产环境下,复制集合实例有3个,我们都配到了连接串中。是否应该只连接一台,我个人也没有很好的解释,理论上应用只需要一个入口即可,后续都交给数据库处理。
2 连接超时设置是否应该显示设置?
https://docs.mongodb.com/manu... 官方有针对连接串的参考说明。
谈到超时问题,我们来看数据库连接周期
一次完整的请求包括三个阶段:1、建立连接 2、数据传输 3、断开连接。
通常我们谈到的超时分为两种,connectTimeout 和socketTimeout,前者是网络连接超时,后者是执行超时。
如果与数据库服务器请求建立连接的时间超过ConnectionTimeOut,就会抛 ConnectionTimeOutException,即服务器连接超时,没有在规定的时间内建立连接。如果服务器处理数据用时过长,超过了SocketTimeOut,就会抛SocketTimeOutExceptin,即服务器响应超时,服务器没有在规定的时间内返回给客户端数据。(这里的异常是java驱动返回的异常)
这两个参数,官方给出的是 connectTimeoutMS和socketTimeoutMS
生产环境下关于options参数
我们在生产环境下,参数replicaSet,connectTimeoutMS,socketTimeoutMS都没有配置。
官方文档
https://docs.mongodb.com/manu...
https://docs.mongodb.com/manu...
https://docs.mongodb.com/manu...
文章中的观点有不严谨之处,欢迎评论沟通,关于副本集,笔者也是在不断探索中。
抱着不确定性思维,学习MongoDb数据库的基本态度:边学习,边实践,边参考,边改进,在问题中成长。
欢迎关注公众号《图南科技》