目录
一、mongodb介绍
二、mongodb安装
三、连接mongodb
四、mongodb用户管理
五、mongodb创建集合和数据管理
六、PHP的mongodb扩展
七、PHP的mongo扩展
八、mongodb副本集介绍
九、mongodb副本集搭建
十、mongodb副本集测试
一、mongodb介绍
官网www.mongodb.com, 当前最新版3.4
C++编写,基于分布式的,属于NoSQL的一种
在NoSQL中是最像关系型数据库的
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档、数组及文档数组。
关于JSON http://www.w3school.com.cn/json/index.asp
因为基于分布式,所以很容易扩展
-
MongoDB和关系型数据库对比
-
关系型数据库数据结构
-
MongoDB数据结构
二、mongodb安装
epel自带的mongodb版本为2.6,我们需要安装3.4版本
官方安装文档https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/
cd /etc/yum.repos.d/
vim mongodb-org-3.4.repo//加入如下内容
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
yum list |grep mongodb //可以看到mongodb相关的rpm包
yum install -y mongodb-org
#创建官方yum源
[root@minglinux-01 ~] cd /etc/yum.repos.d
[root@minglinux-01 /etc/yum.repos.d] vim mongodb-org-3.4.repo
#写入以下内容
1 [mongodb-org-3.4]
2 name=MongoDB Repository
3 baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
4 gpgcheck=1
5 enabled=1
6 gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
#查看mongodb相关的rpm包
[root@minglinux-01 /etc/yum.repos.d] yum list |grep mongodb
collectd-write_mongodb.x86_64 5.8.1-1.el7 epel
mongodb.x86_64 2.6.12-6.el7 epel
mongodb-org.x86_64 3.4.19-1.el7 mongodb-org-3.4
mongodb-org-mongos.x86_64 3.4.19-1.el7 mongodb-org-3.4
mongodb-org-server.x86_64 3.4.19-1.el7 mongodb-org-3.4
mongodb-org-shell.x86_64 3.4.19-1.el7 mongodb-org-3.4
mongodb-org-tools.x86_64 3.4.19-1.el7 mongodb-org-3.4
mongodb-server.x86_64 2.6.12-6.el7 epel
mongodb-test.x86_64 2.6.12-6.el7 epel
nodejs-mongodb.noarch 1.4.7-1.el7 epel
php-mongodb.noarch 1.0.4-1.el7 epel
php-pecl-mongodb.x86_64 1.1.10-1.el7 epel
poco-mongodb.x86_64 1.6.1-3.el7 epel
syslog-ng-mongodb.x86_64 3.5.6-3.el7 epel
#安装mongodb
[root@minglinux-01 /etc/yum.repos.d] yum install -y mongodb-org
三、连接mongodb
systemctl start mongod //启动服务
在本机可以直接运行命令mongo进入到mongodb shell中
如果mongodb监听端口并不是默认的27017,则在连接的时候需要加--port 选项,例如
mongo --port 27018
连接远程mongodb,需要加--host,例如
mongo --host 127.0.0.1
如果设置了验证,则在连接的时候需要带用户名和密码
mongo -uusername -ppasswd --authenticationDatabase db //这个和MySQL挺像
[root@minglinux-01 /etc/yum.repos.d] vim /etc/mongod.conf #配置文件
···
27 net:
28 port: 27017
29 bindIp: 127.0.0.1,192.168.162.130 #限制访问的IP,增加IP用逗号隔开
#将此行注释掉则允许所有的地址访问。
···
[root@minglinux-01 /etc/yum.repos.d] systemctl start mongod #启动mongodb
[root@minglinux-01 /etc/yum.repos.d] ps aux |grep mongod
mongod 9213 18.3 1.9 973408 36132 ? Sl 16:39 0:01 /usr/bin/mongod -f /etc/mongod.conf
root 9242 0.0 0.0 112720 976 pts/0 S+ 16:39 0:00 grep --color=auto mongod
[root@minglinux-01 /etc/yum.repos.d] netstat -lntp |grep mongod
tcp 0 0 192.168.162.130:27017 0.0.0.0:* LISTEN 9213/mongod
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 9213/mongod
[root@minglinux-01 /etc/yum.repos.d] mongo
MongoDB shell version v3.4.19
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.19
Server has startup warnings:
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
> ^C
bye
[root@minglinux-01 /etc/yum.repos.d] mongo --host 192.168.162.130 --port 27017
MongoDB shell version v3.4.19
connecting to: mongodb://192.168.162.130:27017/
MongoDB server version: 3.4.19
Server has startup warnings:
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T16:39:45.008+0800 I CONTROL [initandlisten]
>
四、mongodb用户管理
use admin//需要切换到admin库
db.createUser( { user: "admin", customData: {description: "superuser"}, pwd: "admin122", roles: [ { role: "root", db: "admin" } ] } )
user指定用户,customData为说明字段,可以省略,pwd为密码,roles指定用户的角色,db指定库名
use admin //切换到admin库
db.system.users.find() //列出所有用户,需要切换到admin库
show users //查看当前库下所有的用户
db.dropUser('admin') //删除用户
若要用户生效,还需要编辑启动脚本vim /usr/lib/systemd/system/mongod.service,在OPTIONS=后面增--auth
重启服务systemctl restart mongod
mongo -u "admin" -p "admin122" --authenticationDatabase "admin"
use db1
db.createUser( { user: "test1", pwd: "123aaa", roles: [ { role: "readWrite", db: "db1" }, {role: "read", db: "db2" } ] } )
test1用户对db1库读写,对db2库只读。
之所以先use db1,表示用户在 db1 库中创建,就一定要db1库验证身份,即用户的信息跟随随数据库。比如上述 test1虽然有 db2 库的读取权限,但是一定要先在db1库进行身份验证,直接访问会提示验证失败。
use db2
db.auth("test1", "123aaa")
> use admin #切换到admin库
switched to db admin
> db.createUser( { user: "admin", customData: {description: "superuser"}, pwd: "admin122", roles: [ { role: "root", db: "admin" } ] } ) #创建admin用户
Successfully added user: {
"user" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> db.system.users.find() #列出所有用户
{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "eNFeSQSyE3mBns9Tkf5bHQ==", "storedKey" : "kRx4Je3+de9ijoqRib9LbSbRKyc=", "serverKey" : "bICd1/FrFJjD70CvGu+KyQqhSiQ=" } }, "customData" : { "description" : "superuser" }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
> show users #查看当前库下所有的用户
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
#再创建一个用户
> db.createUser({user:"Lucci",pwd:"123123",roles:[{role:"read",db:"testdb"}]})
Successfully added user: {
"user" : "Lucci",
"roles" : [
{
"role" : "read",
"db" : "testdb"
}
]
}
#删除Lucci用户
> db.dropUser('Lucci')
true
> show users
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
#若要新建用户生效,还需要编辑启动脚本
[root@minglinux-01 /etc/yum.repos.d] vim /usr/lib/systemd/system/mongod.service
···
9 Environment="OPTIONS=--auth -f /etc/mongod.conf" #增加--auth
···
[root@minglinux-01 /etc/yum.repos.d] systemctl restart mongod
Warning: mongod.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[root@minglinux-01 /etc/yum.repos.d] systemctl daemon-reload
[root@minglinux-01 /etc/yum.repos.d] systemctl restart mongod #重启一哈
[root@minglinux-01 /etc/yum.repos.d] ps aux |grep mongod
mongod 10623 2.7 2.2 973412 41824 ? Sl 17:05 0:00 /usr/bin/mongod --auth -f /etc/mongod.conf
root 10672 0.0 0.0 112720 980 pts/0 S+ 17:06 0:00 grep --color=auto mongod
#多了--auth才能使用创建用户和密码登录
#测试
[root@minglinux-01 /etc/yum.repos.d] mongo --host 192.168.162.130 --port 27017
MongoDB shell version v3.4.19
connecting to: mongodb://192.168.162.130:27017/
MongoDB server version: 3.4.19
> use admin
switched to db admin
> show users #报错未授权
2019-03-06T17:09:22.146+0800 E QUERY [thread1] Error: not authorized on admin to execute command { usersInfo: 1.0 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.getUsers@src/mongo/shell/db.js:1539:1
shellHelper.show@src/mongo/shell/utils.js:797:9
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1
#重新使用admin登录
[root@minglinux-01 /etc/yum.repos.d] mongo --host 192.168.162.130 --port 27017 -u "admin" -p "admin122" --authenticationDatabase "admin"
MongoDB shell version v3.4.19
connecting to: mongodb://192.168.162.130:27017/
MongoDB server version: 3.4.19
Server has startup warnings:
2019-03-06T17:05:46.735+0800 I CONTROL [initandlisten]
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten]
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-06T17:05:46.736+0800 I CONTROL [initandlisten]
> use admin
switched to db admin
> show users
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> use db1
switched to db db1
> db.createUser( { user: "test1", pwd: "123aaa", roles: [ { role: "readWrite", db: "db1" }, {role: "read", db: "db2" } ] } )
Successfully added user: { #创建test1用户对db1库读写,对db2库只读
"user" : "test1",
"roles" : [
{
"role" : "readWrite",
"db" : "db1"
},
{
"role" : "read",
"db" : "db2"
}
]
}
> use db2
switched to db db2
> db.auth('test1','123aaa')
Error: Authentication failed. #在db2中验证失败
0
> use db1
switched to db db1
> db.auth('test1','123aaa') #test1用户在 db1 库中创建,就一定要db1库验证身份
1
- MongoDB用户角色
Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限
- MongoDB库管理
db.version() //查看版本
use userdb //如果库存在就切换,不存在就创建
show dbs //查看库,此时userdb并没有出现,这是因为该库是空的,还没有任何集合,只需要创建一个集合就能看到了
db.createCollection('clo1') //创建集合clo1,在当前库下面创建
db.dropDatabase() //删除当前库,要想删除某个库,必须切换到那个库下
db.stats() //查看当前库的信息
db.serverStatus() //查看mongodb服务器的状态
五、mongodb创建集合和数据管理
db.createCollection("mycol", { capped : true, size : 6142800, max : 10000 } ) //语法:db.createCollection(name,options)
name就是集合的名字,options可选,用来配置集合的参数,参数如下
capped true/false (可选)如果为true,则启用封顶集合。封顶集合是固定大小的集合,当它达到其最大大小,会自动覆盖最早的条目。如果指定true,则也需要指定尺寸参数。
autoindexID true/false (可选)如果为true,自动创建索引_id字段的默认值是false。
size (可选)指定最大大小字节封顶集合。如果封顶如果是 true,那么你还需要指定这个字段。单位B
max (可选)指定封顶集合允许在文件的最大数量。
#MongoDB创建集合
> db.createCollection("mycol", { capped : true, size : 6142800, max : 10000 } )
{ "ok" : 1 }
> show tables
mycol
> show collections
mycol
#MongoDB数据管理
> db.Account.insert({AccountID:1,UserName:"abc",password:"123456"})
WriteResult({ "nInserted" : 1 })
> show tables #Account集合不存在,直接插入数据,则mongodb会自动创建Account集合
Account
mycol
> db.Account.insert({AccountID:2,UserName:"zxc",password:"654321"})
WriteResult({ "nInserted" : 1 })
> db.Account.update({AccountID:1},{"$set":{"Age":20}}) #更新文档
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.Account.find() #查看所有文档
{ "_id" : ObjectId("5c7fbe6fe904efb00d2a7d12"), "AccountID" : 1, "UserName" : "abc", "password" : "123456", "Age" : 20 }
{ "_id" : ObjectId("5c7fbf20e904efb00d2a7d13"), "AccountID" : 2, "UserName" : "zxc", "password" : "654321" }
#根据条件查询
> db.Account.find({AccountID:2})
{ "_id" : ObjectId("5c7fbf20e904efb00d2a7d13"), "AccountID" : 2, "UserName" : "zxc", "password" : "654321" }
#根据条件删除
> db.Account.remove({AccountID:1})
WriteResult({ "nRemoved" : 1 })
> db.Account.find()
{ "_id" : ObjectId("5c7fbf20e904efb00d2a7d13"), "AccountID" : 2, "UserName" : "zxc", "password" : "654321" }
#删除所有文档,即删除集合
> db.Account.drop()
true
> show tables
mycol #集合Account已被删除
#进入对应的库,查看集合状态
> use db1
switched to db db1
> db.printCollectionStats()
mycol
{
"ns" : "db1.mycol",
"size" : 0,
"count" : 0,
"storageSize" : 4096,
"capped" : true,
"max" : 10000,
"maxSize" : 6142976,
"sleepCount" : 0,
"sleepMS" : 0,
"wiredTiger" : {
"metadata" : {
"formatVersion" : 1
},
···
···
六、PHP的mongodb扩展
cd /usr/local/src/
git clone https://github.com/mongodb/mongo-php-driver
cd mongo-php-driver
git submodule update --init
/usr/local/php-fpm/bin/phpize
./configure --with-php-config=/usr/local/php-fpm/bin/php-config
make && make install
vi /usr/local/php-fpm/etc/php.ini //增加 extension = mongodb.so
/usr/local/php-fpm/bin/php -m
还可以到pecl官网上下载mongodb的扩展源码包
cd /usr/local/src/
wget https://pecl.php.net/get/mongodb-1.3.0.tgz
tar zxvf mongodb-1.3.0.tgz
cd mongodb-1.3.0
/usr/local/php-fpm/bin/phpize
./configure --with-php-config=/usr/local/php-fpm/bin/php-config
make && make install
vi /usr/local/php-fpm/etc/php.ini //增加 extension = mongodb.so
/usr/local/php-fpm/bin/php -m
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] cd /usr/local/src/
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] wget https://pecl.php.net/get/mongodb-1.3.0.tgz
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] tar -zxvf mongodb-1.3.0.tgz
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] cd mongodb-1.3.0/
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] /usr/local/php/bin/phpize
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] ./configure --with-php-config=/usr/local/php-fpm/bin/php-config #nginx是php-fpm
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] make
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] make install
Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] ls /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
memcache.so mongodb.so opcache.a opcache.so redis.so
#编辑/usr/local/php/etc/php.ini增加 extension = mongodb.so
[root@minglinux-01 /usr/local/src/mongodb-1.3.0] vim /usr/local/php-fpm/etc/php.ini #注意这里是php-fpm
root@minglinux-01 ~] /usr/local/php-fpm/bin/php -m |grep mongo
mongodb #mongodb扩展模块已加载
[root@minglinux-01 ~] /etc/init.d/php-fpm restart #重启一下php-fpm
Gracefully shutting down php-fpm . done
Starting php-fpm done
七、PHP的mongo扩展
到pecl官网上下载mongo的扩展源码包
cd /usr/local/src/
wget https://pecl.php.net/get/mongo-1.6.16.tgz
tar zxvf mongodb-1.6.16.tgz
cd mongodb-1.6.16
/usr/local/php-fpm/bin/phpize
./configure --with-php-config=/usr/local/php-fpm/bin/php-config
make && make install
vi /usr/local/php-fpm/etc/php.ini //增加 extension = mongo.so
/usr/local/php-fpm/bin/php -m
[root@minglinux-01 /usr/local/src/mongo-1.6.16] cd /usr/local/src/
[root@minglinux-01 /usr/local/src/mongo-1.6.16] wget https://pecl.php.net/get/mongo-1.6.16.tgz
[root@minglinux-01 /usr/local/src/mongo-1.6.16] tar -zxvf mongo-1.6.16.tgz
[root@minglinux-01 /usr/local/src/mongo-1.6.16] cd mongo-1.6.16/
[root@minglinux-01 /usr/local/src/mongo-1.6.16] /usr/local/php-fpm/bin/phpize
[root@minglinux-01 /usr/local/src/mongo-1.6.16] ./configure --with-php-config=/usr/local/php-fpm/bin/php-config
[root@minglinux-01 /usr/local/src/mongo-1.6.16] make
[root@minglinux-01 /usr/local/src/mongo-1.6.16] make install
Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
[root@minglinux-01 /usr/local/src/mongo-1.6.16] ls /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
memcache.so mongodb.so mongo.so opcache.a opcache.so redis.so
[root@minglinux-01 /usr/local/src/mongo-1.6.16] vim /usr/local/php-fpm/etc/php.ini #增加 extension = mongo.so
[root@minglinux-01 /usr/local/src/mongo-1.6.16] /usr/local/php-fpm/bin/php -m |grep mongo
mongo
mongodb
[root@minglinux-01 /usr/local/src/mongo-1.6.16] /etc/init.d/php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm done
- 测试mongo扩展
参考文档 https://docs.mongodb.com/ecosystem/drivers/php/
http://www.runoob.com/mongodb/mongodb-php.html
vim /data/wwwroot/default/mongo.php //增加
<?php
$m = new MongoClient(); // 连接
$db =$m->test; // 获取名称为 "test" 的数据库
$collection = $db->createCollection("runoob");
echo "集合创建成功";
?>
curl localhost/mongo.php
[root@minglinux-01 /usr/local/src/mongo-1.6.16] vim /data/wwwroot/default/mongo.php
1 <?php
2 $m = new MongoClient(); // 连接
3 $db =$m->test; // 获取名称为 "test" 的数据库
4 $collection = $db->createCollection("runoob");
5 echo "集合创建成功";
6 ?>
[root@minglinux-01 /usr/local/src/mongo-1.6.16] curl localhost/mongo.php
集合创建成功
#编辑启动脚本删除--auth关闭用户认证连接然后连接MongoDB查看
[root@minglinux-01 /usr/local/src/mongo-1.6.16] vim /usr/lib/systemd/system/mongod.service
[root@minglinux-01 /usr/local/src/mongo-1.6.16] systemctl daemon-reload
[root@minglinux-01 /usr/local/src/mongo-1.6.16] systemctl restart mongod
[root@minglinux-01 /usr/local/src/mongo-1.6.16] curl localhost/mongo.php
集合创建成功
[root@minglinux-01 /usr/local/src/mongo-1.6.16] mongo --host 192.168.162.130 --port 27017
···
> use test
switched to db test
> show tables
runoob #集合创建成功
八、mongodb副本集介绍
早期版本使用master-slave,一主一从和MySQL类似,但slave在此架构中为只读,当主库宕机后,从库不能自动切换为主
目前已经淘汰master-slave模式,改为副本集,这种模式下有一个主(primary),和多个从(secondary),只读。支持给它们设置权重,当主宕掉后,权重最高的从切换为主
在此架构中还可以建立一个仲裁(arbiter)的角色,它只负责裁决,而不存储数据
在此架构中读写数据都是在主上,要想实现负载均衡的目的需要手动指定读库的目标server
- 副本集架构图
九、mongodb副本集搭建
三台机器: 192.168.162.130(primary) 192.168.162.132(secondary) 192.168.162.128(secondary)
编辑三台机器的配置文件,更改或增加:
replication://把此行前面的#删除
##oplog大小
oplogSizeMB: 20//前面有两个空格
##复制集名称
replSetName: aminglinux//前面有两个空格
分别重启三台机器
连接主,在主上运行命令mongo
>use admin
>config={_id:"minglinux",members:[{_id:0,host:"192.168.162.130:27017"},{_id:1,host:"192.168.162.132:27017"},{_id:2,host:"192.168.162.128:27017"}]}
>rs.initiate(config)
minglinux:OTHER> rs.status() //查看状态
如果两个从上的状态为"stateStr" : "STARTUP", 则需要进行如下操作
> var config={_id:"minglinux",members:[{_id:0,host:"192.168.162.130:27017"},{_id:1,host:"192.168.162.132:27017"},{_id:2,host:"192.168.162.128:27017"}]}
>rs.reconfig(config)
此时再次查看rs.status()会发现从的状态变为SECONDARY
#首先在02和03两台机器上安装mongodb
#在192.168.162.130(primary)机器将mongodb-org-3.4.repo传到其他两台机器上
[root@minglinux-01 ~] cat /etc/yum.repos.d/mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
[root@minglinux-01 ~] rsync -av !$ root@192.168.162.132:/etc/yum.repos.d/mongodb-org-3.4.repo
rsync -av /etc/yum.repos.d/mongodb-org-3.4.repo root@192.168.162.132:/etc/yum.repos.d/mongodb-org-3.4.repo
root@192.168.162.132's password:
sending incremental file list
mongodb-org-3.4.repo
[root@minglinux-01 ~] rsync -av !$ root@192.168.162.132:/etc/yum.repos.d/mongodb-org-3.4.repo
[root@minglinux-01 ~] rsync -av /etc/yum.repos.d/mongodb-org-3.4.repo root@192.168.162.128:/etc/yum.repos.d/mongodb-org-3.4.repo
#192.168.162.132(secondary)安装mongodb
[root@minglinux-02 ~] ls /etc/yum.repos.d/mongodb-org-3.4.repo
/etc/yum.repos.d/mongodb-org-3.4.repo #将文件中https改为http安装速度更快
[root@minglinux-02 ~] yum install -y mongodb-org
#192.168.162.128(secondary)安装mongodb
[root@minglinux-03 ~] ls /etc/yum.repos.d/mongodb-org-3.4.repo
/etc/yum.repos.d/mongodb-org-3.4.repo #将文件中https改为http安装速度更快
[root@minglinux-03 ~] yum install -y mongodb-org
#三台机器均按如下所示修改配置文件
[root@minglinux-01 ~] vim /etc/mongod.conf
···
27 net:
28 port: 27017
29 bindIp: 127.0.0.1,192.168.162.130 #增加本机内网ip,secondary用secondary的ip
···
36 replication:
37 ##oplog大小
38 oplogSizeMB: 20 #前面有两个空格
39 ##复制集名称
40 replSetName: minglinux #前面有两个空格
···
[root@minglinux-01 ~] systemctl restart mongod #重启一下服务
[root@minglinux-01 ~] ps aux |grep mongo
mongod 2655 1.8 2.6 1018984 48796 ? Sl 15:11 0:00 /usr/bin/mongod -f /etc/mongod.conf
root 2681 0.0 0.0 112720 984 pts/1 S+ 15:11 0:00 grep --color=auto mongo
##若用户认证连接没去掉则编辑启动脚本/usr/lib/systemd/system/mongod.service删除OPTIONS后面的--auth,然后执行systemctl daemon-reload
[root@minglinux-01 ~] netstat -lntp |grep mongod
tcp 0 0 192.168.162.130:27017 0.0.0.0:* LISTEN 2025/mongod
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 2025/mongod
[root@minglinux-01 ~] iptables -nvL #三台机器都需要保证iptables没有设置规则以免阻断通信
Chain INPUT (policy ACCEPT 78862 packets, 21M bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 77332 packets, 22M bytes)
pkts bytes target prot opt in out source destination
#在192.168.162.130(primary)上连接mongoDB服务
[root@minglinux-01 ~] mongo
···
···
> use admin
switched to db admin
> config={_id:"minglinux",members:[{_id:0,host:"192.168.162.130:27017"},{_id:1,host:"192.168.162.132:27017"},{_id:2,host:"192.168.162.128:27017"}]}
{
"_id" : "minglinux",
"members" : [
{
"_id" : 0,
"host" : "192.168.162.130:27017"
},
{
"_id" : 1,
"host" : "192.168.162.132:27017"
},
{
"_id" : 2,
"host" : "192.168.162.128:27017"
}
]
}
> rs.initiate(config) #初始化,启动一个新的副本集
{ "ok" : 1 }
minglinux:OTHER> rs.status() #查看副本集状态
{
"set" : "minglinux",
"date" : ISODate("2019-03-08T08:03:36.065Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.162.130:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2617,
"optime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-03-08T08:03:30Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1552032179, 1),
"electionDate" : ISODate("2019-03-08T08:02:59Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.162.132:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 47,
"optime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-03-08T08:03:30Z"),
"optimeDurableDate" : ISODate("2019-03-08T08:03:30Z"),
"lastHeartbeat" : ISODate("2019-03-08T08:03:35.232Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T08:03:34.229Z"),
"pingMs" : NumberLong(11),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.162.130:27017",
"syncSourceHost" : "192.168.162.130:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.162.128:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 47,
"optime" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1552032210, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-03-08T08:03:30Z"),
"optimeDurableDate" : ISODate("2019-03-08T08:03:30Z"),
"lastHeartbeat" : ISODate("2019-03-08T08:03:35.232Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T08:03:34.228Z"),
"pingMs" : NumberLong(12),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.162.130:27017",
"syncSourceHost" : "192.168.162.130:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1
}
十、mongodb副本集测试
主上建库,建集合
use mydb
db.acc.insert({AccountID:1,UserName:"123",password:"123456"})
show dbs
从上查看
show dbs
若出现错误Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" },需要执行
rs.slaveok()
#在主上建库建集合
minglinux:PRIMARY> use admin
switched to db admin
minglinux:PRIMARY> use mydb
switched to db mydb
minglinux:PRIMARY> db.acc.insert({AccountID:1,UserName:"123",password:"123456"})
WriteResult({ "nInserted" : 1 })
minglinux:PRIMARY> show dbs
admin 0.000GB
db1 0.000GB
local 0.000GB
mydb 0.000GB
test 0.000GB
minglinux:PRIMARY> use mydb
switched to db mydb
minglinux:PRIMARY> show tables
acc
#在192.168.162.132(secondary) 上连接mongodb查看
[root@minglinux-02 ~] mongo
···
···
minglinux:SECONDARY> show dbs
2019-03-09T00:56:02.077+0800 E QUERY [thread1] 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:62:1
shellHelper.show@src/mongo/shell/utils.js:814:19
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1
minglinux:SECONDARY> rs.slaveOk()
minglinux:SECONDARY> show dbs
admin 0.000GB
db1 0.000GB
local 0.000GB
mydb 0.000GB
test 0.000GB
minglinux:SECONDARY> use mydb
switched to db mydb
minglinux:SECONDARY> show tables
acc
#在192.168.162.128(secondary) 上连接mongodb查看
[root@minglinux-03 ~] mongo
···
···
minglinux:SECONDARY> show dbs
2019-03-08T17:06:30.760+0800 E QUERY [thread1] 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:62:1
shellHelper.show@src/mongo/shell/utils.js:814:19
shellHelper@src/mongo/shell/utils.js:704:15
@(shellhelp2):1:1
minglinux:SECONDARY> rs.slaveOk()
minglinux:SECONDARY> show dbs
admin 0.000GB
db1 0.000GB
local 0.000GB
mydb 0.000GB
test 0.000GB
minglinux:SECONDARY> use mydb
switched to db mydb
minglinux:SECONDARY> show tables
acc
- 副本集更改权重模拟主宕机
默认三台机器权重都为1,如果任何一个权重设置为比其他的高,则该台机器马上切换为primary角色,所以我们预设三台机器的权重分别为:130:3,132:2,128:1
在主上执行
cfg = rs.conf()
cfg.members[0].priority = 3
cfg.members[1].priority = 2
cfg.members[2].priority = 1
rs.reconfig(cfg)
这样的话,第二个节点将会成为候选主节点。
主上执行 iptables -I INPUT -p tcp --dport 27017 -j DROP
# rs.config()可以查看到当前三台机器权重都为1
minglinux:PRIMARY> rs.config()
#模拟主宕机
[root@minglinux-01 ~] iptables -I INPUT -p tcp --dport 27017 -s 192.168.162.0/24 -j DROP
[root@minglinux-01 ~] mongo
···
···
minglinux:SECONDARY> rs.status() #可以看到192.168.162.132变成了PRIMARY,因为权重都一样,PRIMARY也可能是192.168.162.132
{
"set" : "minglinux",
"date" : ISODate("2019-03-08T10:30:09.998Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "192.168.162.128:27017",
"syncSourceHost" : "192.168.162.128:27017",
"syncSourceId" : 2,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.162.130:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 11410,
"optime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2019-03-08T18:30:13Z"),
"syncingTo" : "192.168.162.128:27017",
"syncSourceHost" : "192.168.162.128:27017",
"syncSourceId" : 2,
"infoMessage" : "syncing from: 192.168.162.128:27017",
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "192.168.162.132:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 27,
"optime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2019-03-08T18:30:13Z"),
"optimeDurableDate" : ISODate("2019-03-08T18:30:13Z"),
"lastHeartbeat" : ISODate("2019-03-08T10:30:05.391Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T10:29:30.393Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1552069793, 1),
"electionDate" : ISODate("2019-03-08T18:29:53Z"),
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.162.128:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 27,
"optime" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1552069813, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2019-03-08T18:30:13Z"),
"optimeDurableDate" : ISODate("2019-03-08T18:30:13Z"),
"lastHeartbeat" : ISODate("2019-03-08T10:30:05.391Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T10:29:30.406Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.162.132:27017",
"syncSourceHost" : "192.168.162.132:27017",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1
}
#给三台机器设置不同的权重
[root@minglinux-01 ~] iptables -D INPUT -p tcp --dport 27017 -s 192.168.162.0/24 -j DROP #先将iptables规则删掉,规则删掉后PRIMAR不会自动还原,除非权重大
#在新的PRIMAR上设置权重
minglinux:PRIMARY> cfg=rs.conf()
···
minglinux:PRIMARY> cfg.members[0].priority = 3
3
minglinux:PRIMARY> cfg.members[1].priority = 2
2
minglinux:PRIMARY> cfg.members[2].priority = 1
1
minglinux:PRIMARY> rs.reconfig(cfg)
minglinux:SECONDARY> rs.config()
{
"_id" : "minglinux",
"version" : 2,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "192.168.162.130:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "192.168.162.132:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 2,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.162.128: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" : 60000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5c8221a8bbb206bd7db2b34b")
}
}
#机器权重已修改成功
#PRIMAR变成了192.168.162.130机器,因为它的权重最高
minglinux:SECONDARY> rs.status()
{
"set" : "minglinux",
"date" : ISODate("2019-03-08T18:55:02.686Z"),
"myState" : 2,
"term" : NumberLong(3),
"syncingTo" : "192.168.162.128:27017",
"syncSourceHost" : "192.168.162.128:27017",
"syncSourceId" : 2,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1552070865, 44),
"t" : NumberLong(3)
},
"appliedOpTime" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"durableOpTime" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.162.130:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1046,
"optime" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2019-03-08T18:47:45Z"),
"optimeDurableDate" : ISODate("2019-03-08T18:47:45Z"),
"lastHeartbeat" : ISODate("2019-03-08T18:55:01.853Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T18:55:01.158Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1552070865, 2),
"electionDate" : ISODate("2019-03-08T18:47:45Z"),
"configVersion" : 2
},
{
"_id" : 1,
"name" : "192.168.162.132:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 12081,
"optime" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2019-03-08T18:47:45Z"),
"syncingTo" : "192.168.162.128:27017",
"syncSourceHost" : "192.168.162.128:27017",
"syncSourceId" : 2,
"infoMessage" : "",
"configVersion" : 2,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "192.168.162.128:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 10321,
"optime" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1552070865, 45),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2019-03-08T18:47:45Z"),
"optimeDurableDate" : ISODate("2019-03-08T18:47:45Z"),
"lastHeartbeat" : ISODate("2019-03-08T18:55:01.787Z"),
"lastHeartbeatRecv" : ISODate("2019-03-08T18:55:01.760Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "192.168.162.130:27017",
"syncSourceHost" : "192.168.162.130:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 2
}
],
"ok" : 1
}