MongoDB运维注意点

Posted 11号树屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB运维注意点相关的知识,希望对你有一定的参考价值。

#监控项

##lastCommittedOpTime  从该成员的角度来看, 己写入大多数副本集成员的最新操作时间。

##appliedOpTime 从该成员的角度来看,己应用于副本集的该成员的最新操作 时间 。

##durableOpTime 从该成员的角度来看,己写入该副本集的该成员的journal 日志的时间(持久化)。

rs.status()  "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1581649735, 1), "t" : NumberLong(10) }, "lastCommittedWallTime" : ISODate("2020-02-14T03:08:55.557Z"), "readConcernMajorityOpTime" : { "ts" : Timestamp(1581649735, 1), "t" : NumberLong(10) }, "readConcernMajorityWallTime" : ISODate("2020-02-14T03:08:55.557Z"), "appliedOpTime" : { "ts" : Timestamp(1581649735, 1), "t" : NumberLong(10) }, "durableOpTime" : { "ts" : Timestamp(1581649735, 1), "t" : NumberLong(10) }, "lastAppliedWallTime" : ISODate("2020-02-14T03:08:55.557Z"), "lastDurableWallTime" : ISODate("2020-02-14T03:08:55.557Z") },


#不停服开启认证

3.4以后的版本可以0 downtime开启认证

配置security.transitionToAuth   那么 mongod 或 mangos 将不强制执行用户访问控制 ,用 户可以使用正确的用户名+密码登录或者不使用用户名+密码登录

  1. 创建角和用户

  2. 客户端调整登录方式为使用用户名密码(在完成本教程时,副本集会拒绝未经身份验 证的 户端连接 现在执行此步骤可确保客户端在转换之前和之后连接到副本集〉

  3. keyfile并且复到每个副本集器上

  4. 副本集从库成员逐个开启transitionToAuth(如果只开启 keyfile 那么成员之间及客户端连接必须经过认证,而其他成员还没有开启 keyfile, 因此会出现这个集群的状态是 other和 recovering):

  5. 主库 stepdown 并开启上述第 4 步(这一步完成后整个集群都开启了 transitionToAuth+keyfile,此时使用或者不使用密码登录都可以操作库)。

  6. 副本集从库成员逐个去掉 transitionToAuth (去掉后就必须使用密码登录而没去掉的成 员依旧能够使用非密码登录)

  7. 主库 stepdown 并关闭上述第 4 步的 transitionToAuth

security : keyFile : <path-to-keyfile> transitionToAuth: true #clusterAuthMode : "keyFile" 这个默认就是 keyFile,加不加该参数都可以 。


#权限控制

类似mysql里面的 user@'10.10.10.1' 限制具体的账号和来源IP

db.createUser( {user: "sys_admin"pwd :"MANAGER"roles: [ { role: "root", db: "admin"} ] ,authenticationRestrictions: [ { clientSource: ["192.168.1.251"],serverAddress: ["192.168.1.249"]}]}


#登录mongos,开始数据的balancer

mongos> sh.startBalancer(){ "ok" : 1, "operationTime" : Timestamp(1581656202, 4), "$clusterTime" : { "clusterTime" : Timestamp(1581656202, 4), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }}


#Change Streams

可用于订阅数据库变更,类似MySQL的binlog,需要开启特性参数featureCompatibilityVersion


#现实操作案例


1、手动调整oplog的大小

注意:可能配置了延迟从库,可能有部分的oplog还没有被应用,调整的时候被"drop"了,就会导致延迟从库处于recovering的状态

aram:PRIMARY> db.adminCommand({replSetResizeOplog:1,size:990}){ "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1581920540, 1), "signature" : { "hash" : BinData(0,"FoeYhA6XytTrrqZYoxgH0SAHTpI="), "keyId" : NumberLong("6790691969011023874") } }, "operationTime" : Timestamp(1581920540, 1)}aram:PRIMARY> db.printReplicationInfo()configured oplog size: 990MBlog length start to end: 839367secs (233.16hrs)oplog first event time: Fri Feb 07 2020 21:13:03 GMT+0800 (CST)oplog last event time: Mon Feb 17 2020 14:22:30 GMT+0800 (CST)now: Mon Feb 17 2020 14:22:33 GMT+0800 (CST)

2、备份

使用 PerconaMongoDB 3.2.12之后的版本,可以实现在线备份。只对wiredTiger 有效,其他需要使用逻辑全备。

db.runCommand({createBackup1, backupDir: "/home/mongod/backup/202002031917/"})

3、最大连接数

在 sharding 架构中,我们应当使用 net.maxIncomingConnections 参数对 mangos 和 mongod 的最大连接数进行管理和限制, 在 mongos 中限制其最大连接, mongod 的连接数应大于所有 mongos 的最大连接数之和 。如果 mongos 连接数的上限很大, 而 monogd 连接数的上限配置得很小,就会出现连接数不够的问题。

1)、可以设置net: maxIncomingConnections: 100002)、 如果没有显示的设置,使用ps -ef | grep $mongo_portcat /proc/$pid/limits cat /proc/26886/limits (查看Max open files )Limit Soft Limit Hard Limit UnitsMax resident set unlimited unlimited bytesMax processes 7173 7173 processesMax open files 65535 65535 files
而数据库中查看连接数:shard1:SECONDARY> db.serverStatus().connections{ "current" : 16, "available" : 52412, "totalCreated" : 60, "active" : 1 }
52412+16=52428=65535*0.8(也就是默认使用了系统连接数的80%)

4、remove 分片

#查看分片信息sh.status()#查看分片详细信息sh.status(true)#删除某个分片db.runCommand( { removeShard : "s1" } )如果这个片是基片,则需要手动的迁移这个片上的数据到其他的分片,db.runCommand( { movePrimary: "test2", to: "s2" })之后再次的removeShard

5、分片chunk迁移会造成极其实例负载,需要设置维护窗口

#登录配置信息库use configconfig:PRIMARY> db.settings.find(){ "_id" : "balancer", "mode" : "full", "stopped" : false }{ "_id" : "autosplit", "enabled" : true }
#更新数据迁移的窗口时间是02-06config:PRIMARY> db.settings.update({"_id" : "balancer"},{$set:{activeWindow:{start:"02",stop:"06"}}},{upsert:true})WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })#两个参数需要组合起来使用 ,意思是如果_secondarγThrottletrue,则使用 writeConcem 选项来指定迁移时写数据的策略#如果 secondaryThrottle 为 false,则使用{w:1}选项来指定迁 移时写数据的策略。config:PRIMARY> db.settings.update({"_id" : "balancer"},{$set:{"_secondaryThrottle":true,"writeConcern":{"w":"majority"}}},{upsert:true})WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })config:PRIMARY> db.settings.find(){ "_id" : "balancer", "mode" : "full", "stopped" : false, "activeWindow" : { "start" : "02", "stop" : "06" } }{ "_id" : "autosplit", "enabled" : true }#取消balancer窗口时间db.settings.update({"_id" : "balancer" }, {$unset : {activeWindow : true }})

6、集群开启sharding功能

必须是在mongos上开启,而正常的sharding集群,需要有mongos   configsvr  shardsvr集群

注意:这里如果对一个集群开启sharding功能,整个集群中对于非空集合必须都有索引,开启之前需要创建索引,如果集群从库还有延迟,执行shardCollection会报错

#在mongos上开启sharding功能mongos> sh.enableSharding("test")#或者mongos> db.runCommand({enablesharding:"test"})#通过执行以上命令,可以让数据库跨shard,如果不执行这步,数据库只会存放在一个shard,一旦激活数据库分片,数据库中不同的collection将被存放在不同的shard上,但一个collection仍旧存放在同一个shard上,要使单个collection也分片,还需单独对collection作些操作
#hash 方式#sh.shardCollection("<database>.<collection>", { <shard key field> : "hashed" } )#range 方式#sh.shardCollection("<database>.<collection>", { <shard key field> : 1, ... } )
#eg.mongos> sh.shardCollection("test2.books",{id:"hashed"})或者mongos> db.runCommand( { shardcollection : "test2.books", key : { id : 1 } } );

7、如何强制重新配置副本集

背景:一主两从,其中一从down 机,新的从库加进来,为了替代宕机的从库,但恢复的时候发现是逻辑备份,因此“kill”掉,重新使用物理备份进行恢复。此时,副本集共4个成员, 2个DOWN机,主库降级,剩余的都是Secondary。

第一想法是删除一个坏掉的从库达到基数,而 rs.remove 要求在 Primary 上执行,此时主库降级 ,集群中只有两个 Secondary,也就是集群中现在没有任何的 Primary 节点,导致不能够使用 rs.remove 命令, 整个集群处于只读状态,不能对外提供写服务。

cfg = rs.conf()cfg .members = [cfg.members[O] , cfg .members[2]] rs.reconfig(cfg, {force : true})

注意:强制重配后会导致 version 版本号过高,这个要注意。如果有异常操作导致高版本号( version)的从库被加入低版本号的同副本集中, 则会导致集群中的低版本号从库旧节点被“remove”,并变成 other状态。

rs.conf()#可以看到"version" : 10
conf=rs.conf()conf.members[2].priority=0.5rs.reconfig(conf,{force:true})rs.conf()#可以看到"version" : 87564



8、快速的将一个库下所有几个重命名到另外一个库去,也就是修改库名,注意提前授权,shard集群不能这么用

var source = "competitive"; #######原库名var dest = "product"; #########新库名var colls = db .getSiblingDB(source).getCollectionNames() ; for (var i = 0; i < colls.length; i++) {var from = source + "." + colls[i] ;var to= dest+"."+colls[i];db.adminCommand({renameCollection : from , to : to}) ;

9、主从数据一致性检查

#这个操作在大库上比较耗时,并且会阻塞操作,使用要慎重

use testdatabase#主库执行aram:PRIMARY> db.runCommand({dbHash:1})
#从库执行aram:SECONDARY> db.runCommand({dbHash:1}){ "host" : "host2:37023", "collections" : { "test1" : "ab6ff428c57ee3f00e3d038a9244aa60" }, "capped" : [ ], "uuids" : { "test1" : UUID("22b61310-e2b9-439c-8884-5fb86a1c3756") }, "md5" : "e3e8455252075bf52292f6c8bafd0d60", "timeMillis" : 288, "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1582684073, 1), "signature" : { "hash" : BinData(0,"MwlkG5oHaM/0SDApLgwxiva2vk4="), "keyId" : NumberLong("6795093206682828802") } }, "operationTime" : Timestamp(1582684073, 1)}


#复制

  • 所有的库在remove的时候,需要关注投票节点是否具备大多数节点,否则集群会降级为只读

  • MongoDB是异步复制的,从库可能会有延迟

  • 在 MongoDB 中,客户端可以在写入真正落盘之前看写入的结果, 即 ReadUncommitted

  • 无论 writeconcern 是如何配置的,当客户端使用“ local”或“ available”  readConcern 时, 其他客户端都可以在写入操作发给客户端确认之前看到写入操作的结果


MongoDB支持的WriteConncern选项如下 

w: 数据写入到number个节点才向用客户端确认 

  • {w: 0} 对客户端的写入不需要发送任何确认,适用于性能要求高,但不关注正确性的场景 

  • {w: 1} 默认的writeConcern,数据写入到Primary就向客户端发送确认

  • {w: “majority”} 数据写入到副本集大多数成员后向客户端发送确认,适用于对数据安全性要求比较高的场景,该选项会降低写入性能 


j: 写入操作的journal持久化后才向客户端确认 默认为”{j: false},如果要求Primary写入持久化了才向客户端确认,则指定该选项为true 


wtimeout: 写入超时时间,仅w的值大于1时有效。 

当指定{w: }时,数据需要成功写入number个节点才算成功,如果写入过程中有节点故障,可能导致这个条件一直不能满足, 从而一直不能向客户端发送确认结果,针对这种情况,客户端可设置wtimeout选项来指定超时时间,当写入过程持续超过该时间仍未结束, 则认为写入失败。 


{w: 1}、{j: true}等writeConcern选项很好理解,Primary等待条件满足发送确认;但{w: "majority"}则相对复杂些, 需要确认数据成功写入到大多数节点才算成功,而MongoDB的复制是通过Secondary不断拉取oplog并重放来实现的,并不是Primary 主动将写入同步给Secondary,

那么Primary是如何确认数据已成功写入到大多数节点的? 

1、Client向Primary发起请求,指定writeConcern为{w: "majority"},Primary收到请求,本地写入并记录写请求到oplog,然后等待 大多数节点都同步了这条/批oplog(Secondary应用完oplog会向主报告最新进度)。 

2、Secondary拉取到Primary上新写入的oplog,本地重放并记录oplog。为了让Secondary能在第一时间内拉取到主上的oplog, find命令支持一个awaitData的选项,当find没有任何符合条件的文档时,并不立即返回,而是等待最多maxTimeMS (默认为2s)时间看 是否有新的符合条件的数据,如果有就返回;所以当新写入oplog时,备立马能获取到新的oplog。 

3、Secondary上有单独的线程,当oplog的最新时间戳发生更新时,就会向Primary发送replSetUpdatePosition命令更新自己的oplog时间戳。 

4、当Primary发现有足够多的节点oplog时间戳已经满足条件了,向客户端发送确认。


如何修改WriteConncern

默认:rs.conf() "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }#修改WriteConncern,大多数节点,并且5s超时cfg= rs.conf()cfg.settings.getLastErrorDefaults = { w :"majority",wtimeout:5000}rs.reconfig(cfg )
rs.conf() "getLastErrorDefaults" : { "w" : "majority", "wtimeout" : 5000 }

假设复制集内投票成员(后续介绍)的数量为 N,则大多数为 N/2+1 ,当复制集内存活成员数不足大多数时,整个复制集将无法选举出 Primary,复制集将无法提供写服务,处于只读 状态 之所以使用奇数个节点,是由于偶数节点和奇数节点容忍失效数一致,所以基数节点从成本和冗余角度讲更具性价比 ,


Secondary 节点配置的方法如下

1、可以配置 Seconday 节点为 Priority 0,这样该节点就无法被选举为 Primary 节点,这样的Secondary 节点可以用作冷备节点 。2、可以配置隐藏的 Secondary节点,这样应用就无法从这类隐藏的节点上读取数据。3、可以配置延迟节点,用于误操作数据恢复 。


注意事项

  • Priority 0 节点的选举优先级为 0,不会被选举为 primary,多机房部署的时候,可以设置主节点机房之外的其他机房的priority为0。

  • vote=0的节点,priority必须是0。

  • Hidden节点 priority必须是0,如果是vote=1的,则在移除的时候需要关注整个集群的vote节点是不是大多数,否则集群降级为只读。

  • Delayed 节点必须是 Hidden 节点,priority=0。

  • vote=1的节点只能从vote=1的节点同步数据。


只有下面几种状态的节点才能发起选举

PRIMARY SECONDARY RECOVERING ARBITER ROLLBACK #回滚只会发生在主节点的写操作,没能成功的在从节点上应用,主节点就“ Down”掉的情况下 。#如何避免 rollback? w 默认为 1,使用 majority 来保证写操作已经达到大多数从节点#怎么避免这个,具体参见:MongoDB 的Rollback讲解及避免


#分片

  • 分片集合时选的 shardkey在分片后不能改变,且分片集合只能有一个 shardkey

  • 如果要分割非空集合,则集合必须具有以分片键开头的索引 对于空集合,如果集合尚不具有指定分 片键的适当索引,则 MongoDB 会自动为其创建索引

  • 对于包含分片键或复合分片键的前缀的查询, mongos 可以将查询定位到特定的分片或分片中,这些有针对性的操作通常比向群中的个分片更高效。

  • 如果询不包括 shardkey或使用符合 shardkey开头的引,则 mongos执行整个分片扫操作,查询分片架构中的所有分片,这种操作耗时非常长

  • 数据库可以有分片和非分片集合的混合,分片集合被分区并分布在集群中的分片上 Unsharded 集合存储在 主分片上 个数据库都有自己的 主分片。如下图所示,只有test2是分片的库,test db1  db2都是没有分片的,主分片在不同的副本集上


  • 分片架构需要至少两个 Shard

  • 用户、客户端或应用程序只有维护 Shard集群时,才需要直连 Shard里的 mongod。其他情况都应该连接mongos访问集群

  • mongos 在执行 create databases 命令时,会选择集群中具有最少数据量的 Shard 来作为primary shardmongos 使用 listDatabase 命令返回的 totalSize 字段作为选择条件的一部分。

部署 config server 时,以下限制适用于副本集配置:

  • 不能有仲裁节点

  • 不能有延迟成员

  • 必须能构建索引(应该将 buildlndexes 设置为 true)


注意!!!:在线上主库发送故障转移后,从库会变为新主,在原主库重新排除故障上线之前应更改新主库的优先级为本副本集中最高,防止原主库上线后以高优先级强制重新抢占主库的地位,导致部分事务丢失或者连接抖动


以上是关于MongoDB运维注意点的主要内容,如果未能解决你的问题,请参考以下文章

mongodb 的注意点

nodejs注意点

MongoDB秒级备份恢复

没有 MongoDB 版本可用于您的部署。运维管理器 mongodb

(转)mongodb常用命令脚本化-自动化运维

运维监控开发笔记