单节点的 MongoDB
在数据的安全和冗余方面是比较低的,在生产环境中,我们为 MongoDB
配置副本集,这样可以提高数据的高可用性和安全性。
副本集 :是一组 Mongod
维护相同数据集的实例。副本集可以包含多个数据承载点和多个仲裁点。在承载数据的节点中,仅有一个节点被视为主节点,其他节点称为次节点。
副本集的节点角色:
Primary 主节点,用于承担Secondary 次节点Arbiter 仲裁节点,也是属于次节点主节点接收所有的数据写入 *** 作,主节点记录数据的所有更改,即oplog
。
将一个额外的mongod
实例添加到副本集作为 仲裁节点。仲裁节点不维护数据集。仲裁节点的目的是通过响应其他副本集成员的心跳和选举请求来维护副本集中的选举。因为它们不存储数据集,所以仲裁节点可以是提供副本集仲裁功能的好方法,其资源成本比具有数据集的全功能副本集成员更低。如果您的副本集具有偶数个成员,请添加仲裁者以避免脑裂出现。
在主节点未与配置中的其它成员通信超过 10s(默认为10s)的话,则符合条件的次节点将推选自己为主节点。
在选举成功完成之前,副本集无法处理写入 *** 作。
electionTimeoutMillis
默认值为10000(10s) ,我们可以根据自己的项目情况来升高或者降低该值,我们在更改该值的时候需要考虑到网络延迟等因素。
默认情况下,副本集在选取新的主节点的等待时间不超过12秒(主要用于将原有主节点标记为不可用,并选举出新的主节点),
副本集数据同步为了保持次节点与主节点的数据同步,MongoDB 使用两种方式进行数据的同步:
初始同步, 用于同步主节点的所有数据
初始同步将所有的数据从副本集的一个成员复制到另外一个成员
增量同步,在初始同步后不断复制新的数据
Oplog 详解在初始同步后不断复制数据,次节点从主节点中同步复制 Oplog,并在异步过程中应用这些 *** 作
MongoDB-Oplog详解
注意副本集在部署前需要确定成员数据,副本集最多能有50个节点,但是只能有7个节点拥有被选举权,副本集需要具有奇数个投票成员,如果有偶数个的话,可以添加一个 仲裁者,来保证有奇数个成员,避免脑裂情况发生,
尽量使用 主机名 来寻找对应的节点,而不是使用 ip 地址,避免 ip 改变导致配置需要更改。
二、副本集部署部署准备部署需要更改 /etc/hosts 文件,将主机名和 ip 地址对应好,不应该使用ip。
使用统一的端口。
创建数据储存的位置和配置文件的位置。
确定好副本集的名称
搭建架构选择
三节点,一个主节点,一个次节点,一个仲裁节点
副本集部署基本环境: 系统 CentOS 7 MongoDB 版本 4.0.83个节点fymongodb001 内网IP:172.18.186.161 公网ip: 47.112.129.2 # 主节点fymongodb002 内网IP: 172.18.186.162 公网ip: 47.112.131.231 # 次节点fymongodb003 内网IP: 172.18.186.163 公网ip: 47.112.98.64 # 仲裁节点副本集名称: fymongodb
三个节点都需要执行
# 下载mongodb cat <<EOF >>/etc/hosts172.18.186.161 fymongodb001172.18.186.162 fymongodb002172.18.186.163 fymongodb003EOFcd /tmp && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.8.tgztar -zxf mongodb-linux-x86_64-4.0.8.tgz mv mongodb-linux-x86_64-4.0.8 /opt/mongodbmkdir /opt/mongodb/{data,logs}useradd mongodb# 我们这里使用的配置文件 是YAML 格式的wget https://raw.githubusercontent.com/tobewithyou1996/linuxGuIDe/master/MongoDB/mongodb_rep.yaml -P /opt/mongodb/chown -R mongodb:mongodb /opt/mongodb/cat <<EOF >>/usr/lib/systemd/system/mongodb.service[Unit]Description= mongodb service manager[Service]# Other directives omitted# (file size)limitFSIZE=infinity# (cpu time)limitcpu=infinity# (virtual memory size)limitAS=infinity# (locked-in-memory size)limitMEmlock=infinity# (open files)limitNOfile=64000# (processes/threads)limitNPROC=64000Type=forkingUser=mongodbGroup=mongodbPIDfile=/opt/mongodb/logs/mongod.pIDExecStart= /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb_rep.yamlExecStop= /opt/mongodb/bin/mongod --shutdown --dbpath /opt/mongodb/dataRestart=always[Install]WantedBy=multi-user.targetEOF# 添加环境变量echo "export PATH=$PATH:/opt/mongodb/bin" >>/etc/profilesource /etc/profile# 启动 systemctl start mongodb
主节点 *** 作
# 主节点 *** 作[root@fymongodb001 tmp]# mongoMongoDB shell version v4.0.8connecting to: mongodb://127.0.0.1:27017/?gssAPIServicename=mongodbImplicit session: session { "ID" : UUID("77f60167-1d37-4796-bf2a-60cfdc4b0526") }MongoDB server version: 4.0.8> use admin # 切换到 admin 数据库switched to db admin # 初始化副本集,副本集名称为 fymongodb ,第一个成员为自己本身。> rs.initiate({_ID:'fymongodb',members: [{ _ID: 0,host: "fymongodb001:27017"}]}) { "ok" : 1 } fymongodb:SECONDARY> # 接着回车,直到显示这个节点为Primary主节点fymongodb:PRIMARY> # 接着添加 次节点 fymongodb002# 添加次节点fymongodb:PRIMARY> rs.add('fymongodb002:27017'){ "ok" : 1,"operationTime" : Timestamp(1555663440,1),"$clusterTime" : { "clusterTime" : Timestamp(1555663440,"signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyID" : NumberLong(0) } }}# 添加仲裁节点fymongodb:PRIMARY> rs.addArb("fymongodb003:27017"){ "ok" : 1,"operationTime" : Timestamp(1555663631,"$clusterTime" : { "clusterTime" : Timestamp(1555663631,"keyID" : NumberLong(0) } }}# 查看当前配置fymongodb:PRIMARY> rs.conf(){ "_ID" : "fymongodb","version" : 3,"protocolVersion" : NumberLong(1),"writeConcernMajorityJournalDefault" : true,"members" : [ { "_ID" : 0,"host" : "fymongodb001:27017","arbiterOnly" : false,"buildindexes" : true,"hIDden" : false,"priority" : 1,"Tags" : { },"slaveDelay" : NumberLong(0),"Votes" : 1 },{ "_ID" : 1,"host" : "fymongodb002:27017",{ "_ID" : 2,"host" : "fymongodb003:27017","arbiterOnly" : true,"priority" : 0,"Votes" : 1 } ],"settings" : { "chainingallowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : -1,"catchUpTakeoverDelayMillis" : 30000,"getLastErrorModes" : { },"getLastErrorDefaults" : { "w" : 1,"wtimeout" : 0 },"replicasetID" : ObjectID("5cb98534cd9d16ff3f4fffdc") }}# rs.status() 查看各个节点的身份
当我们完成上面的 *** 作的时,我们主节点更改的数据已经是会自动同步到次节点的。
次节点 *** 作
fymongodb002
次节点(Secondary)设置允许读写 *** 作。
[root@fymongodb002 ~]# mongoMongoDB shell version v4.0.8connecting to: mongodb://127.0.0.1:27017/?gssAPIServicename=mongodbImplicit session: session { "ID" : UUID("f353edd5-d79a-4947-9844-7f9bde98a949") }MongoDB server version: 4.0.8fymongodb:SECONDARY> fymongodb:SECONDARY> show dbs; # 我们发现无法读写2019-04-19T17:04:40.852+0800 E query [Js] Error: ListDatabases Failed:{ "operationTime" : Timestamp(1555664675,"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codename" : "NotMasterNoSlaveOk","$clusterTime" : { "clusterTime" : Timestamp(1555664675,"keyID" : NumberLong(0) } }} :fymongodb:SECONDARY> rs.slaveOk() # 允许 次节点 进行读取fymongodb:SECONDARY> show dbs; # 我们就可以查看到次节点的数据了。admin 0.000GBconfig 0.000GBdjx 0.000GBlocal 0.000GBfymongodb:SECONDARY> use djx;switched to db djxfymongodb:SECONDARY> show collections; # 从主节点同步过来的数据。djxlsp
数据同步测试测试数据的同步,我们在主节点创建一个集合test
并添加一条数据 'age':38
,我们可以看到次节点也同步了该数据。
测试一
模拟主节点 fymongodb001
宕机了,然后查看次节点 fymongodb002
是否会被选举成为主节点。
我们可以看到 fymongodb002
选举为主节点.
测试二
当 fymongodb002
选举为主节点后,fymongodb001
恢复了,fymongodb001
会作为次节点加入。
测试三
测试在次节点(Secondary)进行数据删除。是删除不了的。
fymongodb:SECONDARY> db.test.drop()2019-04-19T21:48:38.140+0800 E query [Js] Error: drop Failed: { "operationTime" : Timestamp(1555681711,"errmsg" : "not master","code" : 10107,"codename" : "NotMaster","$clusterTime" : { "clusterTime" : Timestamp(1555681711,"I+dFkOHcdqW+La7xvy8JFij+5CY="),"keyID" : NumberLong("6681517989155569665") } }} :_getErrorWithCode@src/mongo/shell/utils.Js:25:13DBCollection.prototype.drop@src/mongo/shell/collection.Js:707:1@(shell):1:1
配置副本集登录验证副本集配置用户和密码,登录主节点,添加admin
用户。
> use adminswitched to db admin> db.createuser({ user: "admin",pwd: "9toc7tpji8",roles: [{ role: "root",db: "admin" }] })Successfully added user: { "user" : "admin","roles" : [ { "role" : "root","db" : "admin" } ]}
在主节点生成 keyflIE
并复制到其它两个节点
# 生成 keyfileopenssl rand -base64 90 -out /opt/mongodb/keyfile#并复制到其它两个节点scp /opt/mongodb/keyfile fymongodb002:/opt/mongodb/scp /opt/mongodb/keyfile fymongodb003:/opt/mongodb/
更改三个节点的 keyfile
文件权限和所有者
chmod 600 /opt/mongodb/keyfile # 一定要更改成 600 权限,否正会报错chown mongodb:mongodb /opt/mongodb/keyfile # 更改文件所有者
更改三个节点的 mongodb_rep.yaml
配置文件,将 security
的参数 authorization
设置为 enabled
,并配置
keyfile
的路径。
security: authorization: "enabled" keyfile: '/opt/mongodb/keyfile' clusterauthMode: "keyfile"
然后依次重启 fymongodb001
、 fymongodb002
、 fymongodb003
。
# fymongodb001systemctl restart mongodb # fymongodb002systemctl restart mongodb # fymongodb003systemctl restart mongodb
登陆 fymongodb001
,我们使用 db.auth()
进行登陆验证。
fymongodb:PRIMARY> show dbs;fymongodb:PRIMARY> use admin switched to db adminfymongodb:PRIMARY> db.auth('admin','9toc7tpji8')1fymongodb:PRIMARY> show dbs;admin 0.000GBconfig 0.000GBlocal 0.000GB
三 、副本集维护副本集成员如何以单节点启动副本集当做单节点启动需要更改配置文件,主要的配置文件有以下几点:
注释副本集名称设置,replSet=fymongodb
更改端口如果是分片储存的,那么还需要注释分片配置,添加 skipShardingConfigurationChecks = true。然后我们执行维护完后,关闭节点
use admindb.shutdownServer()
然后还原原来的配置,然后作为副本集成员加入副本集。
副本集设置节点的优先级如果我们想让某个节点成为主节点,或者是当主节点 down 了后,你想指定某个节点 优先级更高地成为 次节点。
cfg = rs.conf()cfg.members[0].priority = 0.5cfg.members[1].priority = 0.5cfg.members[2].priority = 1rs.reconfig(cfg)
副本集使用备份数据进行启动# 使用备份数据进行启动mongod --dbpath /data/db # 删除 local 数据库use localdb.dropDatabase()# 指定副本集名称并以备份数据 启动mongod --dbpath /data/db --replSet <replname># 启动副本集rs.initiate( { _ID : <replname>,members: [ { _ID : 0,host : <host:port> } ]})
副本集数据量比较大时如何添加次节点当副本集的数据量比较大的时候,我们添加新的节点的时候,如果使用初始化同步的话,会给主节点造成比较大的压力。我们有以下选择:
暂停当前副本集中的一个次节点,然后将 次节点的数据(data)复制到要新添加的节点的数据目录。然后再将两个节点启动。(建议先测试)
如果要复制数据文件,请确保您的副本包含
local
数据库的内容。
指定同步节点 rs.syncFrom(hostportstr)
,指定同步节点为次节点,默认的是同步节点 是主节点。
但是该设置在重新启动节点,或者同步指定的新节点的连接被关闭了,是会失效的。(建议先测试)
如果我们决定还是从主节点进行同步数据。
副本集延迟节点延迟节点在此未记录,详细见官方文档。
副本集常用命令# 副本集初始化rs.initiate( { _ID : "rs0",members: [ { _ID: 0,host: "mongodb0.example.net:27017" },{ _ID: 1,host: "mongodb1.example.net:27017" },{ _ID: 2,host: "mongodb2.example.net:27017" } ]})# 副本集添加成员rs.add('mongodb3.example.net:27017')# 副本集添加仲裁节点rs.addArb('mongodb4.example.net:27017')# 移除节点rs.remove('hostportstr')# 查看当前的配置rs.conf()# 查看各个节点状态和身份rs.status()# 设定某个节点多少秒不可成为主节点rs.freeze(secs)# 设置次节点从指定节点同步数据rs.syncFrom(hostportstr)# 降低主节点为次节点,只能在主节点上运行rs.stepDown([stepdownSecs,catchUpSecs])# 查看帮助rs.help()# 次节点执行,表示允许次节点读取数据rs.slaveOk()# 判断当前节点是否是主节点rs.isMaster()# 查看 Oplog 信息rs.printReplicationInfo()# 查看副本集的次节点与主节点延迟db.printSlaveReplicationInfo()# 移除原有副本集命令use localdb.system.replset.remove({})# 关闭 mongodb进程服务use admindb.shutdownServer()
四、注意事项建议将副本集至少部署在3个可用区。
配置副本集成员,使用的是主机名而不是 ip,因为 ip 可能变动。
副本集包含奇数个投票成员。
错误问题报错内容:
Failed global initialization: BadValue: replication.replSetname is not allowed when storage.indexbuildretry is specifIEd
storage
参数 indexbuildretry
不能与 副本集共存,当开启 副本集的时候,就需要将indexbuildretry
参数注释。官网链接
总结Changed in version 4.0: The setting
storage.indexBuildRetry
cannot be used in conjunction withreplication.replSetName
.
以上是内存溢出为你收集整理的MongoDB-副本集搭建与管理全部内容,希望文章能够帮你解决MongoDB-副本集搭建与管理所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)