搭建高可用 mongodb 集群-副本集

环境装备

  • 三台机器

prosvr-6cf7-191010 172.19.30.240
prosvr-ea03-191010 172.19.20.187
prosvr-dd0e-191010 172.19.40.70

  • 关闭 Transparent HugePages

从 rhel6 开始系统将默认对所有程序开启 transparent_hugepage(THP),linux 内核将尽可能的尝试分配 2M 的页大小给程序使用,内核空间在内存中自身是 2M 对齐的,目的是减少内核 TLB(现代 CPU 使用一小块关联内存,用来缓存最近访问的虚拟页的 PTE。这块内存称为 translation lookaside buffer)的压力,增大 page 大小自然会减少 TLB 大小。如果内存没有 2M 连续大小的空间可分配,内核会回退到分配 4KB 页的方案。THP 页也是可以换出的,这是通过把 2M 的大页分割成 4KB 的普通页实现的。

内核通过增加一个 khugepaged 内核线程,来不停的寻找连续的足够大的尽量对其的内存区域来满足内存分配请求。这个线程会偶尔尝试使用大的内存分配来替换连续的小内存页以最大化 THP 的使用。

ORACLE 和 mongodb 数据库不建议开启 THP,THP 在运行时动态分配内存,可能会带来运行时内存分配的延误。

数据库应用不建议开启 Transparent HugePages

查看系统是否开启了 THP 命令

[root@prosvr-6cf7-191010 logs]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

[root@prosvr-6cf7-191010 logs]# cat /sys/kernel/mm/transparent_hugepage/defrag
always defer defer+madvise [madvise] never

实时生效命令,机器重启后会失效

[root@prosvr-6cf7-191010 logs]# echo never >> /sys/kernel/mm/transparent_hugepage/enabled

[root@prosvr-6cf7-191010 logs]# echo never >> /sys/kernel/mm/transparent_hugepage/defrag

[root@prosvr-6cf7-191010 logs]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]

[root@prosvr-6cf7-191010 logs]# cat /sys/kernel/mm/transparent_hugepage/defrag
always defer defer+madvise madvise [never]

设置机器重启后还生效
在 /etc/rc.local 中加入如下命令

[root@prosvr-6cf7-191010 logs]# cat <<EOF>> /etc/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never >> /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
    echo never >> /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF

或者通过修改 grub 启动参数来实现

[root@prosvr-ea03-191010 logs]# cat /etc/default/grub
GRUB_TIMEOUT=1
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet idle=halt biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8 noibrs"
GRUB_DISABLE_RECOVERY="true"


GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet idle=halt biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8 noibrs"
这一行修改为
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet idle=halt biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8 noibrs transparent_hugepage=never"
并执行
[root@prosvr-ea03-191010 logs]# grub2-mkconfig -o /boot/grub2/grub.cfg

安装 mongodb

  • 下载安装包解压

https://www.mongodb.com/download-center/community

选择适合自己环境的安装包(此处选择 v4.0.12 centos7 的安装包)

image.png

三台节点做同样的操作

[root@prosvr-6cf7-191010 packages]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.12.tgz
--2019-10-10 21:35:01--  https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.12.tgz
正在解析主机 fastdl.mongodb.org (fastdl.mongodb.org)... 13.249.171.96, 13.249.171.61, 13.249.171.9, ...
正在连接 fastdl.mongodb.org (fastdl.mongodb.org)|13.249.171.96|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:105865380 (101M) [application/x-gzip]
正在保存至: “mongodb-linux-x86_64-rhel70-4.0.12.tgz”
100%[======================================================================================================================================================================>] 105,865,380  755KB/s 用时 47s    
2019-10-10 21:35:50 (2.13 MB/s) - 已保存 “mongodb-linux-x86_64-rhel70-4.0.12.tgz” [105865380/105865380])

解压并移动到安装路径下

[root@prosvr-6cf7-191010 packages]# tar -zxvf mongodb-linux-x86_64-rhel70-4.0.12.tgz
mongodb-linux-x86_64-rhel70-4.0.12/THIRD-PARTY-NOTICES.gotools
mongodb-linux-x86_64-rhel70-4.0.12/README
mongodb-linux-x86_64-rhel70-4.0.12/THIRD-PARTY-NOTICES
mongodb-linux-x86_64-rhel70-4.0.12/MPL-2
mongodb-linux-x86_64-rhel70-4.0.12/LICENSE-Community.txt
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongodump
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongorestore
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongoexport
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongoimport
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongostat
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongotop
mongodb-linux-x86_64-rhel70-4.0.12/bin/bsondump
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongofiles
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongoreplay
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongod
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongos
mongodb-linux-x86_64-rhel70-4.0.12/bin/mongo
mongodb-linux-x86_64-rhel70-4.0.12/bin/install_compass

[root@prosvr-6cf7-191010 packages]# ls
docker  mongodb-linux-x86_64-rhel70-4.0.12  mongodb-linux-x86_64-rhel70-4.0.12.tgz
[root@prosvr-6cf7-191010 packages]# mv mongodb-linux-x86_64-rhel70-4.0.12 /usr/local/mongodb
[root@prosvr-6cf7-191010 packages]# cd /usr/local/mongodb/
[root@prosvr-6cf7-191010 mongodb]# ls
bin  LICENSE-Community.txt  MPL-2  README  THIRD-PARTY-NOTICES  THIRD-PARTY-NOTICES.gotools
  • 设置数据存储路径

数据库存储路径

[root@prosvr-6cf7-191010 mongodb]# mkdir -p /var/lib/mongodb/data

日志路径

[root@prosvr-6cf7-191010 mongodb]# mkdir -p /var/lib/mongodb/logs

配置文件(三个节点的配置文件完全一样,除了 bind_ip,bind_ip 设置各 db 所在节点的 ip )

[root@prosvr-6cf7-191010 mongodb]# cat /etc/mongodb.conf
port = 27017
bind_ip = 172.19.30.240
dbpath = /mnt/mongodb/data
logpath = /mnt/mongodb/logs/mongo.log
pidfilepath = /usr/local/mongodb/mongo.pid
fork = true
logappend = true
shardsvr = true
directoryperdb = true
replSet = promongodb
maxConns = 1000000
#auth = true
#keyFile = /usr/local/mongodb/keyfile

设置 path 路径

[root@prosvr-6cf7-191010 mongodb]# cat <<EOF>> ~/.bashrc
export PATH="/usr/local/mongodb/bin:$PATH"
EOF

[root@prosvr-6cf7-191010 mongodb]# source ~/.bashrc

设置启动脚本 /etc/init.d/mongodb

[root@prosvr-6cf7-191010 mongodb]# chmod 755 /etc/init.d/mongodb

[root@prosvr-6cf7-191010 mongodb]# cat /etc/init.d/mongodb
#!/bin/bash
#
# mongod        Start up the MongoDB server daemon
#
# source function library
. /etc/rc.d/init.d/functions
MONGOD=/usr/local/mongodb/bin/mongod
CONFIG_FILE=/etc/mongodb.conf
start()
{
    $MONGOD -f $CONFIG_FILE
    echo "MongoDB is running background..."
}
stop()
{
    pkill mongod
    echo "MongoDB is stopped."
}
restart()
{
    stop
    sleep 1
    start
}   
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart}"
esac
  • 依次启动三台 mongodb
[root@prosvr-6cf7-191010 mongodb]# ln -s /etc/init.d/mongodb /usr/local/bin/mongodb

[root@prosvr-6cf7-191010 mongodb]# mongodb start

[root@prosvr-6cf7-191010 mongodb]# /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf

2019-10-10T21:44:29.705+0800 I STORAGE  [main] Max cache overflow file size custom option: 0
about to fork child process, waiting until server is ready for connections.
forked process: 3861
child process started successfully, parent exiting
  • 三台节点都启动完成后,开始配置 mongodb

选一台节点进行配置(172.19.20.187)
执行 mongo 命令登陆

[root@prosvr-6cf7-191010 ~]# mongo 172.19.20.187:27017
MongoDB shell version v4.0.12
connecting to: mongodb://172.19.30.240:27017/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("09fc2af9-f216-4b3e-94f0-d8fef6949c1b") }
MongoDB server version: 4.0.12

# 初始化副本集
> rs.initiate()
{
    "info2" : "no configuration specified. Using a default configuration for the set",
    "me" : "172.19.20.187:27017",
    "ok" : 1,
    "operationTime" : Timestamp(1570721887, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1570721887, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
promongodb:PRIMARY> rs.conf()
{
    "_id" : "promongodb",
    "version" : 1,
    "protocolVersion" : NumberLong(1),
    "writeConcernMajorityJournalDefault" : true,
    "members" : [
        {
            "_id" : 0,
            "host" : "172.19.20.187:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {
        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("5d9f505f4e911e5eb22d2b9e")
    }
}
# 添加另外两个复本集从节点
promongodb:PRIMARY> rs.add("172.19.30.240:27017")
{
    "ok" : 1,
    "operationTime" : Timestamp(1570722034, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1570722034, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
promongodb:PRIMARY> rs.add("172.19.40.70:27017")
{
    "ok" : 1,
    "operationTime" : Timestamp(1570722059, 2),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1570722059, 2),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
# 查看节点顺序
promongodb:PRIMARY> cfg = rs.conf()
{
    "_id" : "promongodb",
    "version" : 3,
    "protocolVersion" : NumberLong(1),
    "writeConcernMajorityJournalDefault" : true,
    "members" : [
        {
            "_id" : 0,
            "host" : "172.19.20.187:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 1,
            "host" : "172.19.30.240:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 2,
            "host" : "172.19.40.70:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {
            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        }
    ],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {
        },
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("5d9f505f4e911e5eb22d2b9e")
    }
}
  • 设置各个节点的优先级

MongoDB副本集通过设置priority 决定优先级,默认优先级为1,priority值是0到100之间的数字,数字越大优先级越高, priority=0,则此节点永远不能成为主节点 primay。

cfg.members[0].priority =1参数,中括号里的数字是执行rs.conf()查看到的节点顺序, 第一个节点是0,第二个节点是 1,第三个节点是 2,以此类推。优先级最高的那个被设置为主节点。

promongodb:PRIMARY> cfg.members[0].priority = 1 
1
promongodb:PRIMARY> cfg.members[1].priority = 1
1
promongodb:PRIMARY> cfg.members[2].priority = 2  //设置_ID 为 2 的节点为主节点。即当当前主节点发生故障时,该节点就会转变为主节点接管服务

使配置生效

promongodb:PRIMARY> rs.reconfig(cfg)
{
    "ok" : 1,
    "operationTime" : Timestamp(1570722179, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1570722179, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
  • 到另外两台从节点上分别进行配置(读写分离需要)
[root@prosvr-ea03-191010 ~]# mongo 172.19.30.240:27017
MongoDB shell version v4.0.12
connecting to: mongodb://172.19.30.240:27017/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f7e1269d-095e-404e-addd-9c9fd4fa1d2a") }
MongoDB server version: 4.0.12

promongodb:SECONDARY> db.getMongo().setSlaveOk() //设置从节点为只读.注意从节点的前缀现在是SECONDARY。看清楚才设置
[root@prosvr-ea03-191010 ~]# mongo 172.19.40.70:27017
MongoDB shell version v4.0.12
connecting to: mongodb://172.19.40.70:27017/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f7e1269d-095e-404e-addd-9c9fd4fa1d2a") }
MongoDB server version: 4.0.12
promongodb:SECONDARY> db.getMongo().setSlaveOk() //设置从节点为只读.注意从节点的前缀现在是SECONDARY。看清楚才设置

设置完只读操作后,从节点将不能执行相关操作

promongodb:SECONDARY> show dbs
2019-10-12T11:22:42.646+0800 E QUERY    [js] Error: listDatabases failed:{
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:139:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1
  • 设置数据库账号,开启登录验证
# 创建账号

[root@prosvr-6cf7-191010 ~]# mongo 172.19.20.187:27017
MongoDB shell version v4.0.12
connecting to: mongodb://172.19.20.187:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("4b65920c-f7e7-42af-ae43-3e9ab3bbba89") }
MongoDB server version: 4.0.12
Welcome to the MongoDB shell.

promongodb:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
promongodb:PRIMARY> use admin
switched to db admin
promongodb:PRIMARY> show collections
system.version
promongodb:PRIMARY> db.createUser({user:"wood",pwd:”xxxxxxx",roles:[{role:"root",db:"admin"}]})
Successfully added user: {
    "user" : "wood",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}
promongodb:PRIMARY> db.auth("wood","xxxxxxx")
1
promongodb:PRIMARY> db.createUser({user:'admin', pwd:’aaxxxxxxx', roles:[{ role:"userAdminAnyDatabase",db:"admin"}]})
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}
promongodb:PRIMARY> db.auth("admin”,"aaxxxxxxx")
1
promongodb:PRIMARY> show collections
system.users
system.version
promongodb:PRIMARY> db.system.users.find(
... )
{ "_id" : "admin.wood", "userId" : UUID("97a7bd6axxxxxxx92-0380abc45d97"), "user" : "wood", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "xxxxxxx+UVZLSCQ==", "storedKey" : “xxxxxxxx=", "serverKey" : “xxxxxxxx=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "admin.admin", "userId" : UUID("5d566ac1xxxxxxx0f3-0445ba50e2cb"), "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "gDxxxxxxxYwaA==", "storedKey" : "/vcccxxxxxxx=", "serverKey" : "+xxxxxxxSmaJXBo=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
promongodb:PRIMARY>
  • 设置 keyfile,用于集群节点之间的通信

副本集服务器,开启--auth参数的同时,必须指定 keyfile 参数,节点之间的通讯基于该 keyfile,key 长度必须在 6 到 1024 个字符之间,

最好为 3 的倍数,不能含有非法字符。

[root@prosvr-dd0e-191010 ~]# cd /usr/local/mongodb/
[root@prosvr-dd0e-191010 mongodb]# openssl rand -base64 21 > keyfile  
[root@prosvr-dd0e-191010 mongodb]# ls
bin  keyfile  LICENSE-Community.txt  mongo.pid  MPL-2  README  THIRD-PARTY-NOTICES  THIRD-PARTY-NOTICES.gotools
[root@prosvr-dd0e-191010 mongodb]# cat keyfile
tBZnTjxxxxxxxye/kxIb21JYnJlZ
[root@prosvr-dd0e-191010 mongodb]#  chmod 600 /usr/local/mongodb/keyfile

去掉 auth=true keyfile= /topath/kefile 的注释

[root@prosvr-dd0e-191010 mongodb]# cat /etc/mongodb.conf
port = 27017
bind_ip = 172.19.40.70
dbpath = /mnt/mongodb/data
logpath = /mnt/mongodb/logs/mongo.log
pidfilepath = /usr/local/mongodb/mongo.pid
fork = true
logappend = true
shardsvr = true
directoryperdb = true
replSet = promongodb
maxConns = 1000000
auth = true
keyFile = /usr/local/mongodb/keyfile
  • 重启 mongodb 服务
[root@prosvr-dd0e-191010 mongodb]# mongodb stop
[root@prosvr-dd0e-191010 mongodb]# mongodb start

将生成的 keyfile 复制到其他两个节点上,并修改同样的配置,重启服务使其生效

[root@prosvr-dd0e-191010 mongodb]# cat keyfile
tBZnTjxxxxxxxye/kxIb21JYnJlZ
  • 依次设置三台 mongodb 的 logrotate
[root@prosvr-dd0e-191010 logs]# cat /etc/logrotate.d/mongodb

/mnt/mongodb/logs/*.log {
    rotate 4
    maxsize 128M
    missingok
    notifempty
    copytruncate
    dateext
    dateformat -%Y%m%d-%s
    compress
}

PS: 若登陆 mongo 时,有 warning 提示

2019-10-10T16:10:02.004+0800 I CONTROL  [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 31813 processes, 65535 files. Number of processes should be at least 32767.5 : 0.5 times number of files.

则可通过设置 mac process limit 超过提示项,并重启 mongodb 即可

一种方式
通过获取 mongodb 的 pid 查看详细情况

[root@prosvr-ea03-191010 ~]# ps -efl |grep mongodb
1 S root      1667     1  0  80   0 - 362746 -     12:21 ?        00:00:23 /usr/local/mongodb/bin/mongod -f /etc/mongodb.conf
0 S root      1931  1560  0  80   0 - 28184 -      13:46 pts/0    00:00:00 grep --color=auto mongodb
[root@prosvr-ea03-191010 ~]# cat /proc/1667/limits
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
**Max processes             31813                31813                processes**
Max open files            65535                65535                files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       31813                31813                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us  
[root@prosvr-ea03-191010 logs]# ulimit -u # 发现系统的 user max processes 即为 31813
31813
# 修改  user max processes 为 42000
[root@prosvr-ea03-191010 logs]# ulimit -u 42000
# 并将改命令写入 /etc/profile
[root@prosvr-ea03-191010 logs]# echo "ulimit -u 42000” >> /etc/profile
# 重启 mongodb 后,再次查看 mongodb 进程的使用情况
[root@prosvr-ea03-191010 ~]# cat /proc/`pgrep mongod`/limits
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
**Max processes             42000                42000                processes**
Max open files            65535                65535                files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       31813                31813                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us

再次 mongo 登陆服务则不再提示

  • 开启 mongodb 自身的监控服务
[https://cloud.mongodb.com/freemonitoring/cluster/VJPV34K25T6P4EIPLVBWTFXEA2W2TUMP](https://cloud.mongodb.com/freemonitoring/cluster/VJPV34K25T6P4EIPLVBWTFXEA2W2TUMP) 
promongodb:PRIMARY> db.enableFreeMonitoring()
{
    "state" : "enabled",
    "message" : "To see your monitoring data, navigate to the unique URL below. Anyone you share the URL with will also be able to view this page. You can disable monitoring at any time by running db.disableFreeMonitoring().",
    "url" : "https://cloud.mongodb.com/freemonitoring/cluster/VXXXXXXXXXXXUMP",
    "userReminder" : "",
    "ok" : 1
}

关闭监控服务

promongodb:PRIMARY> db.disableFreeMonitoring()

![image.png](https://upload-images.jianshu.io/upload_images/9885453-db4583a055b68fc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

客户端连接使用副本集

MongoDB复制集里Primary节点是不固定的,当遇到复制集轮转升级、Primary宕机、网络分区等场景时,复制集可能会选举出一个新的Primary,而原来的Primary则会降级为Secondary,

即发生主备切换。当连接复制集时,如果直接指定Primary的地址来连接,当时可能可以正确读写数据的,但一旦复制集发生主备切换,你连接的Primary会降级为Secondary,将无法继续执行写操作,这将严重影响到你的线上服务。

要正确连接复制集,需要先了解下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://wood:xxxxx@172.19.30.240:27017,172.19.20.187:27017,172.19.40.70:27017/admin?replicaSet=promongodb"); 
MongoClient client = new MongoClient(connectionString);
MongoDatabase database = client.getDatabase(“yourDatabase");
MongoCollection collection = database.getCollection(“yourCollections");
  • 实现读写分离

主节点负责所有的读写操作将会造成主节点压力较大,通过客户端程序实现读写分离

读参数一共有六个参数:primary、primaryPreferred、secondary、secondary、secondaryPreferred、nearest。

  • primary:默认参数,只从主节点上进行读取操作;
  • primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
  • secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
  • secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
  • nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。

读写分离做好后,就可以进行数据分流,减轻压力,解决了"主节点的读写压力过大如何解决?"这个问题。

不过当副本节点增多时,主节点的复制压力会加大有什么办法解决吗?基于这个问题,Mongodb已有了相应的解决方案 - 引用仲裁节点:

在Mongodb副本集中,仲裁节点不存储数据,只是负责故障转移的群体投票,这样就少了数据复制的压力。

其实不只是主节点、副本节点、仲裁节点,还有Secondary-Only、Hidden、Delayed、Non-> Voting,其中:

  • Secondary-Only:不能成为primary节点,只能作为secondary副本节点,防止一些性能不高的节点成为主节点。
  • Hidden:这类节点是不能够被客户端制定IP引用,也不能被设置为主节点,但是可以投票,一般用于备份数据。
  • Delayed:可以指定一个时间延迟从primary节点同步数据。主要用于备份数据,如果实时同步,误删除数据马上同步到从节点,恢复又恢复不了。
  • Non-Voting:没有选举权的secondary节点,纯粹的备份数据节点。

java 程序为例。ReadPreference preference = ReadPreference.secondary(); 设置

public class TestMongoDBReplSet {
    public static void main(String[] args)  {
        try {
            List<ServerAddress> addresses = new ArrayList<ServerAddress>();  
            ServerAddress address1 = new ServerAddress("172.19.40.70" , 27017);
            ServerAddress address2 = new ServerAddress("172.19.20.187" , 27017);
            ServerAddress address3 = new ServerAddress("172.19.30.240" , 27017);
            addresses.add(address1);  
            addresses.add(address2);
            addresses.add(address3);
            MongoClient client = new MongoClient(addresses);
            DB db = client.getDB( "test");
            DBCollection coll = db.getCollection( "test");
            BasicDBObject object = new BasicDBObject();  
            object.append( "key1", "value1" );
           ** ReadPreference preference = ReadPreference.secondary();**  
            DBObject dbObject = coll.findOne(object, null , preference);  
            System. out .println(dbObject);  
        } catch (Exception e) {
            e.printStackTrace();  
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容