MongoDB学习笔记整理


参考:

MongoDB的基本操作

MongoDB的简介和安装启动

简介

  • mongodb是个非关系型数据库,但操作跟关系型数据最类似(mysql是关系型数据库)
  • mongodb是面向文档存储的非关系型数据库,数据以json的格式进行存储
  • mongodb可用来永久存储,也可用来缓存数据
  • mongodb提供副本集和分片集群功能,操作简单

安装

方法一:基于yum源

  1. 配置yum源
vim /etc/yum.repos.d/mongo.repo
    # 社区版
    [mongodb-org-4.2]
    name=MongoDB Repository
    baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/
    gpgcheck=0
    enabled=1
    # gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc

    # 企业版
    [mongodb-enterprise-4.2]
    name=MongoDB Enterprise Repository
    baseurl=https://repo.mongodb.com/yum/redhat/$releasever/mongodb-enterprise/4.2/$basearch/
    gpgcheck=0
    enabled=1
    # gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc
  1. 安装
# 社区版和企业版,二选一,这里选择社区版
yum install -y mongodb-org*
# 如果指定版本和组件包,则使用如下命令
# yum install -y mongodb-org-4.2.6 mongodb-org-server-4.2.6 mongodb-org-shell-4.2.6 mongodb-org-mongos-4.2.6 mongodb-org-tools-4.2.6
# 企业版安装:
# yum install -y mongodb-enterprise
# yum install -y mongodb-enterprise-4.2.6 mongodb-enterprise-server-4.2.6 mongodb-enterprise-shell-4.2.6 mongodb-enterprise-mongos-4.2.6 mongodb-enterprise-tools-4.2.6

可以指定任何可用的MongoDB版本。但是yum ,当有新版本可用时,将升级软件包。为防止意外升级,请固定包装。要固定包,exclude请在/etc/yum.conf文件中添加以下指令:exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools

方法二:基于文件

  1. 如果是局域网环境,可以下载指定版本的rpm文件进行安装
  2. 下载压缩包进行解压运行,社区版地址:https://www.mongodb.com/try/download/communityhttps://www.mongodb.com/download-center/community/releases,企业版地址:https://www.mongodb.com/try/download/enterprisehttps://www.mongodb.com/download-center/enterprise/releases,选择自己想要的版本和安装方式,然后进行下载安装
# 以安装二进制文件为例(解压即运行)
cd /usr/local/src
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.1.tgz
tar -zxvf mongodb-linux-x86_64-rhel70-4.4.1.tgz
mv mongodb-linux-x86_64-rhel70-4.4.1/bin/* /usr/bin
# 验证是否安装成功
ll -h /usr/bin | grep mongo
mongod --help
mongod --version

配置

最简单的单例配置文件

# 创建数据和日志目录
mkdir -p /data/mongodb/27017/
vim /data/mongodb/27017/mongodb.conf
  # 日志
  systemLog:
    destination: file
    logAppend: true
    path: /data/mongodb/27017/mongodb.log
  # 存储
  storage:
    dbPath: /data/mongodb/27017/
    journal:
      enabled: true
  # 进程
  processManagement:
    fork: true
  # 网络
  net:
    port: 27017
    bindIp: 0.0.0.0

【注意事项】:如果是公网服务器,建议监听在127.0.0.1

启动

  1. 启动mongodb服务器:/usr/local/mongodb/bin/mongod -f /data/mongodb/27017/mongodb.conf
  2. mongodb的启动验证:
ll -h /data/mongodb/27017/ #数据文件查看
ps auxf  | grep mongo   #进程查看
netstat -tulnp|grep mongo #端口查看
  1. mongodb的关闭:
kill 关闭 #不建议,后续介绍正确的关闭方法
kill -9和突然断电可能会导致mongodb数据的丢失

bin目录下的几个文件说明

  • mongo:客户端程序,连接MongoDB
  • mongod:服务端程序,启动MongoDB
  • mongodump:备份程序
  • mongoexport:数据导出程序
  • mongofiles:GridFS工具,内建的分布式文件系统
  • mongoimport:数据导入程序
  • mongorestore:数据恢复程序
  • mongos:数据分片程序,支持数据的横向扩展
  • mongostat:监视程序
    从4.4版本开始,mongostat等相关工具不再随着数据库安装包一起发布了,将单独作为一个安装包发布MongoDB Database Tools project,涉及工具如下:mongoimport、mongoexport、mongodump、mongorestore、mongotop、mongostat、bsondump。如需要使用,需要单独下载安装,有rpm包和tar包两种。安装也很简单,就是复制文件到bin目录下就行了。
    工具的安装命令如下:
cd /usr/local/src
wget https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.2/x86_64/RPMS/mongodb-org-tools-4.2.9-1.el7.x86_64.rpm
yum localinstall -y mongodb-org-tools-4.2.9-1.el7.x86_64.rpm

MongoDB服务器的启动优化

mongodb提供一个mongo客户端,类似于mysql提供的客户端命令

mongo 127.0.0.1:27017
mongo #默认连接到127.0.0.1:27017

mongodb启动优化说明

  1. WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine --->建议使用xfs的文件系统
  2. WARNING: Access control is not enabled for the database.Read and write access to data and configuration is unrestricted. --->建议进行用户权限设置
  3. WARNING: You are running this process as the root user, which is not recommended. --->不建议以root用户运行(此建议可以不理)
  4. WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.We suggest setting it to 'never' --->建议禁止Linux的最大内存页
  5. WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.We suggest setting it to 'never' --->建议禁止Linux的最大内存页
  6. WARNING: soft rlimits too low. rlimits set to 3895 processes, 65535 files. Number of processes should be at least 32767.5 : 0.5 times number of files.--->建议将用户进程数修改为65535

优化

具体的系统内核参数设置可以通过命令ulimit -a进行查看

  1. 打开文件数和内核进程数限制放开方式如下:
vim /etc/security/limits.conf
    * - nofile 102400
    * - nproc 65536
# 需要重新登录
  1. 禁止内存巨大页
vim /etc/rc.local
    echo 'never' >/sys/kernel/mm/transparent_hugepage/enabled
    echo 'never' >/sys/kernel/mm/transparent_hugepage/defrag 
chmod +x /etc/rc.d/rc.local #centos7默认rc.local没有执行权限,需要支持执行权限
# /etc/rc.d/rc.local 用于添加开机启动命令,/etc/rc.local是/etc/rc.d/rc.local的软连接
  1. 修改centos7默认的进程数限制
vim /etc/security/limits.d/20-nproc.conf
    *          soft    nproc     65536  # 修改为65536
  1. 使用普通用户启动mongodb
useradd mongodb -s /sbin/nologin
chown -R mongodb:mongodb /data/mongodb/ /usr/local/mongodb/
su - mongodb -s /bin/bash  #  - 改变工作目录为mongodb的用户目录;-s 指定要执行的 shell 
mongod -f /data/mongodb/27017/mongodb.conf 
# 检查是否启动成功
logout # 回到root环境
ps auxf  | grep mongo

MongoDB客户端基础使用

mongodb的基础概念介绍

  • database:数据库
  • collection:集合,类似于mysql中的表
  • filed:类似于mysql中字段
  • document:每行的记录

客户端

mongo客户端的命令自动提示功能(使用tab键)
查询所有的库,默认自带三个库

show dbs
show databases

mongo客户端提供一个正确关闭mongodb服务器的方法

use admin
db.shutdownServer()

数据操作

# mongodb创建库、创建集合、插入数据(key value的字典方式插入)
use shijiange  #use即可,无需显式创建数据库
db.myuser.insert({ name: 'shijiange1', age:28 }) #无需显示创建collection
db.myuser.insert( {'name': 'shijiange2', age: 27} )
db.myuser.insert( {'name': 'shijiange3', age: 26} )
show dbs
    # admin      0.000GB
    # config     0.000GB
    # local      0.000GB
    # shijiange  0.000GB
show collections
    # myuser
show tables
    # myuser

#---------------------------------------------------------------------------

# 查询集合数据,默认有个_id
use shijiange
db.myuser.find()     #查询所有数据
    # { "_id" : ObjectId("5f5b33842e21a0f61eddeef6"), "name" : "shijiange1", "age" : 28 }
    # { "_id" : ObjectId("5f5b341c4bffd59d8b427d3a"), "name" : "shijiange2", "age" : 27 }
    # { "_id" : ObjectId("5f5b34234bffd59d8b427d3b"), "name" : "shijiange3", "age" : 26 }
db.myuser.find( { name: 'shijiange1' } )
    # { "_id" : ObjectId("5f5b33842e21a0f61eddeef6"), "name" : "shijiange1", "age" : 28 }
db.myuser.find( { age: 26 } )
    # { "_id" : ObjectId("5f5b34234bffd59d8b427d3b"), "name" : "shijiange3", "age" : 26 }

#---------------------------------------------------------------------------

# 删除集合数据
use shijiange
db.myuser.remove({ name: 'shijiange2' }) #有条件的删除
db.myuser.find()
    # { "_id" : ObjectId("5f5b33842e21a0f61eddeef6"), "name" : "shijiange1", "age" : 28 }
    # { "_id" : ObjectId("5f5b34234bffd59d8b427d3b"), "name" : "shijiange3", "age" : 26 }
db.myuser.remove( {} )      #删除数据
db.myuser.drop()      #删除集合

# 集合的field虽然不需要固定,但是一般来说不这样子使用
db.myuser.insert( {age: 28} )
db.myuser.insert( {'location': 'hangzhou'} )
db.myuser.find()

# 更新集合数据
use shijiange;
db.myuser.update({ 'location': 'hangzhou' }, { $set: { 'location': 'shanghai' } })
db.myuser.update({ age: 28 }, {$set: { age: 30 }})

# 删除数据库
use shijiange
db.dropDatabase()
# 【注意】:mongodb自带的三个库不要动

MongoDB集合的多种查询方式

# collection数据准备
use shijiange
db.myuser.insert( {name:"shijiange1", age: 20} )
db.myuser.insert( {name:"shijiange2", age: 28} )
db.myuser.insert( {name:"shijiange3", age: 38} )
db.myuser.insert( {name:"zhangsan1", age: 58} )
db.myuser.insert( {name:"zhangsan2", age: 68} )
db.myuser.insert( {name:"zhangsan3", age: 25} )

# pretty易读的方式
db.myuser.find().pretty()

# 查询数据总共的记录数
db.myuser.find().count()

# limit限制条数查询
db.myuser.find()
db.myuser.find().limit(2)    #查看前面两条记录
    # { "_id" : ObjectId("5f5b39cefe38c3fe6a2b7f3e"), "name" : "shijiange1", "age" : 20 }
    # { "_id" : ObjectId("5f5b39cefe38c3fe6a2b7f3f"), "name" : "shijiange2", "age" : 28 }

# 使用skip跳过记录
db.myuser.find().skip(2).limit(2)
    # { "_id" : ObjectId("5f5b39cefe38c3fe6a2b7f40"), "name" : "shijiange3", "age" : 38 }
    # { "_id" : ObjectId("5f5b39cefe38c3fe6a2b7f41"), "name" : "zhangsan1", "age" : 58 }

# mongodb分页查询(每次显示两条,递进显示)
db.myuser.find().skip(0).limit(2)
db.myuser.find().skip(2).limit(2)
db.myuser.find().skip(4).limit(2)

# 使用sort进行排序
db.myuser.find().sort({ age: 1 }) #按age升序
db.myuser.find().sort({ age: -1 }) #按age降序

# 根据字段进行数字比较查询
db.myuser.find({ age: {$lt: 30} })
    # $gt:大于;$lt:小于;$gte:大于或等于;$lte:小于或等于

# 查询多种条件的组合
db.myuser.find( {name: 'shijiange1'} )
db.myuser.find( {name: 'shijiange2'} )
db.myuser.find({ $or: [ {name: 'shijiange1'},{name: 'shijiange2'} ] })
db.myuser.find({ $and: [ {name: 'shijiange1'},{age: 20} ] })

# mongodb正则查询,支持普通正则和扩展正则
db.myuser.find({ name: {$regex: "shijiange[1-9]"} }) #普通正则过滤
db.myuser.find( {"name":{$regex:"(zhangsan)"}} )   #支持分组正则
db.myuser.find({ $and: [ {name:  {$regex: "shijiange[1-9]"}},{age: 20} ] })

MongoDB索引查询与建立

# mongodb数据准备
use shijiange
for(i=1; i<=500000;i++){
  db.myuser.insert( {name:'mytest'+i, age:i} )
}

# mongodb有慢查询的概念,默认是超过100ms会记录慢日志mongodb.log
db.getProfilingStatus()
    # { "was" : 0, "slowms" : 100, "sampleRate" : 1 } # 100为100ms
# 查询age为9999的,查看扫描的行数
# tail -f /data/mongodb/27017/mongodb.log  # 在另一个终端中执行
db.myuser.find( {age:9999} )
db.myuser.find( {age:9999} ).explain(true) #使用explain可以查看是否全表扫描
# 每查询一次,会多出如下一条日志记录:
# {"t":{"$date":"2020-09-11T17:24:01.364+08:00"},"s":"I",  "c":"COMMAND",  "id":51803,   "ctx":"conn3","msg":"Slow query","attr":{"type":"command","ns":"shijiange.myuser","appName":"MongoDB Shell","command":{"find":"myuser","filter":{"age":9999.0},"lsid":{"id":{"$uuid":"b6e162bc-a7d7-4efb-9d6f-e717606b8f67"}},"$db":"shijiange"},"planSummary":"COLLSCAN","keysExamined":0,"docsExamined":500000,"cursorExhausted":true,"numYields":500,"nreturned":1,"queryHash":"3838C5F3","planCacheKey":"3838C5F3","reslen":164,"locks":{"ReplicationStateTransition":{"acquireCount":{"w":501}},"Global":{"acquireCount":{"r":501}},"Database":{"acquireCount":{"r":501}},"Collection":{"acquireCount":{"r":501}},"Mutex":{"acquireCount":{"r":1}}},"storage":{},"protocol":"op_msg","durationMillis":137}}

# 添加索引,加快查询
db.myuser.getIndexes()    #获取当前索引,默认有_id的索引,所以用_id查是比较快
db.myuser.ensureIndex( {age:1} )  #增加age的升序索引
db.myuser.getIndexes()
db.myuser.find( {age:9999} )
db.myuser.find( {age:9999} ).explain(true)
db.myuser.dropIndex( {age:1} )  #删除索引

# 使用正则的话,索引无效果
db.myuser.find( {"name":"mytest1"} )
db.myuser.ensureIndex( {name:1} )   #添加索引
db.myuser.find( {"name":"mytest6"} )
db.myuser.find( {"name":/99999/} )
db.myuser.find( {"name":/99999/} ).explain(true)  #使用正则,全表扫描,也是慢

# mongodb建立唯一索引,唯一索引对应的值不能重复
use shijiange
db.myuser.insert( {userid:1} )
db.myuser.insert( {userid:1} ) # 此时没有建立唯一索引,是可以插入重复值的
db.myuser.remove({})   #清空数据
db.myuser.ensureIndex( {userid:1},{unique:true} )  #创建唯一索引
db.myuser.insert( {userid:1} )
db.myuser.insert( {userid:2} )
db.myuser.insert( {userid:1} )      #因为是唯一索引,所以会报错

MongoDB数据库的监控命令

mongostat可以实时监控mongodb的状态,一直刷新输出

mongostat --help
mongostat  -h 127.0.0.1:27017
mongostat  # 默认监控127.0.0.1:27017

# 测试脚本
use shijiange
for(i=1; i<=300000;i++){
  db.myuser.insert( {name:'mytest'+i, age:i} )
}

# mongodb监控之serverStatus。serverStatus可用来获取mongodb的状态信息
db.serverStatus()   #查看所有的监控信息
db.serverStatus().network #单独查看网络流量信息
db.serverStatus().opcounters #统计增、删、改、查的次数
db.serverStatus().connections #连接

# 使用非交互式shell进行获取
echo 'db.serverStatus()' | mongo
echo 'db.serverStatus().opcounters' | mongo

MongoDB副本集

mongodb单台服务器,数据会有丢失的风险,且单台服务器无法做高可用性。
mongodb副本集能够预防数据丢失,多台mongodb数据一致,mongodb副本集能够在有问题的时候自动切换。

MongoDB副本集的搭建

实验环境介绍:使用3台服务器实战mongodb副本集,生产环境中建议至少三台服务器
3台服务器的ip为:192.168.1.202、192.168.1.203、192.168.1.204

mongodb副本集配置文件

# 配置文件
vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
      destination: file
      logAppend: true
      path: /data/mongodb/27017/mongodb.log
    # 存储
    storage:
      dbPath: /data/mongodb/27017/
      journal:
        enabled: true
    # 进程
    processManagement:  
      fork: true
    # 网络
    net:   
      port: 27017
      bindIp: 0.0.0.0
    # 副本集
    replication:   
      replSetName: shijiange # 目前MongoDB提供了三种Replication方式:Matser/Matser, Matser/Slave,Replica Sets

启动3个mongodb服务器

需要对应更改端口、数据目录、日志路径

# 192.168.1.202、192.168.1.203、192.168.1.204
su - mongodb -s /bin/bash
mongod -f /data/mongodb/27017/mongodb.conf  

mongodb副本集的初始化及其状态查看

# 192.168.1.202,只需要在其中一台上进行初始化即可
mongo
use admin
config = { _id:"shijiange", members:[
  {_id:0,host:"192.168.1.202:27017"},
  {_id:1,host:"192.168.1.203:27017"},
  {_id:2,host:"192.168.1.204:27017"}]
}
rs.initiate( config ) #副本集初始化,需要一定时间
rs.status()  #副本集状态,一个PRIMARY(192.168.1.202),其它SECONDARY。PRIMARY是主,只有PRIMARY能写入

# 测试副本集的数据同步
# 在PRIMARY那台机器上
mongo
use shijiange
db.myuser.insert( {name:"shijiange1", age: 20} )
db.myuser.insert( {name:"shijiange2", age: 28} )
db.myuser.insert( {name:"shijiange3", age: 38} )
db.myuser.insert( {name:"zhangsan1", age: 58} )
db.myuser.insert( {name:"zhangsan2", age: 68} )
db.myuser.insert( {name:"zhangsan3", age: 25} )

# 在SECONDARY机器上查看
rs.secondaryOk() #4.4版本是rs.secondaryOk(),4.0版本是rs.slaveOk()。SECONDARY需要声明是slave才能查看数据【从库无法插入数据】
use shijiange
db.myuser.find()

# 查看slave的延时情况(所有机器都可以执行)
rs.printSlaveReplicationInfo()

MongoDB副本集故障自动切换

mongodb的副本集当primary挂了,会挑选其中的一台secondary升为主。挑选其中一台secondary升级为primary的条件是剩下的集群台数>=2,如果集群只剩下一个实例的话,会有异常。

#mongodb副本集自动切换演示
mongo #连接到primary
use admin
db.shutdownServer() #关闭主mongodb,会有其它mongodb提升为主。插入数据正常

# 关闭第二台
mongo
use admin
db.shutdownServer() #关闭两台mongodb的话,剩下一台不会提升为primary,插入数据将异常

# 同时启动192.168.1.202和192.168.1.203,没有固定的主,可通过优先级指定primary
mongod -f /data/mongodb/27017/mongodb.conf

MongoDB副本集的优先级

primary的选举依赖于各个实例的优先权重,默认权重都是1。副本集的主挑选权重最高的,权重一样的无法控制谁为主。
设置各个实例的优先权重,挑选自己想要的实例为主,只有primary可以更改权重配置

conf = rs.config()   #获取副本集的配置,默认权重都是1
conf.members[0].priority = 5 #索引号从0开始,每次递增1,类似数组(目前这台为primary)
conf.members[1].priority = 10  
conf.members[2].priority = 15 # 让这台变成primary
rs.reconfig(conf)   #更新mongodb副本集的配置,优先权重最高的提升为primary,关闭启动后也为主

MongoDB副本集的伸缩

mongodb副本集的扩展非常好,往副本集里添加实例和移除实例都非常方便。往mongodb副本集添加实例数据能够自动同步,无需人工干预。

# 往现有mongodb副本集中添加实例
# 创建mongodb_4(192.168.1.205)实例,配置和前三台机器一样(虚拟机克隆),注意副本集名称要保持一致replSetName: shijiange
# 连接primary(192.168.1.202)
mongo
use admin
rs.add('192.168.1.205:27017') #数据是自动同步
# rs.add的优先权重默认为1,id是顺序递增的

# 从mongodb副本集中移除实例,不可移除primary
use admin
rs.remove('192.168.1.204:27017')  # 状态由secondary变成other

# 副本集经过添加删除后顺序会乱,设置权重需要注意
rs.config() #获取到后,需要注意每个实例的位置。id不改变,即移除2之后,3不会变成2

MongoDB的备份和恢复

单台服务器一定需要备份,mongodump工具用来备份数据,mongorestore工具用来恢复数据。
mongodb备份说明需要指定ip和端口,单台服务器直接使用mongodump进行备份,副本集需要连接到primary上备份。

# 数据清空,启动单台mongodb(192.168.1.202)
vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
    destination: file
    logAppend: true
    path: /data/mongodb/27017/mongodb.log
    # 存储
    storage:
    dbPath: /data/mongodb/27017/
    journal:
        enabled: true
    # 进程
    processManagement:
    fork: true
    # 网络
    net:
    port: 27017
    bindIp: 0.0.0.0

mongod -f /data/mongodb/27017/mongodb.conf
mongo
use shijiange
db.myuser.insert( {name:"shijiange1", age: 20} )
db.myuser.insert( {name:"shijiange2", age: 28} )
db.myuser.insert( {name:"shijiange3", age: 38} )
db.myuser.insert( {name:"zhangsan1", age: 58} )
db.myuser.insert( {name:"zhangsan2", age: 68} )
db.myuser.insert( {name:"zhangsan3", age: 25} )

# mongodb数据库的备份,备份所有库
mkdir -p /data/mongodbbackup/
mongodump -h 127.0.0.1:27017 -o /data/mongodbbackup/  # 备份所有的库
ll -h /data/mongodbbackup/
    # drwxr-xr-x 2 root root 69 9月  14 17:20 admin
    # drwxr-xr-x 2 root root 53 9月  14 17:20 shijiange

# mongodb数据库的恢复
# 先删除之前的数据
mongorestore -h 127.0.0.1:27017 /data/mongodbbackup/
# 测试数据是否恢复成功
mongo
show dbs
use shijiange
db.myuser.find()

Python操作MongoDB

mongodb可以使用java、python、php等语言去操作,运维使用Python居多,介绍使用python操作Mongodb数据库。

Python简单操作MongoDB

# 使用python操作mongodb,需要使用pip安装pymongo模块
# centos7(python2)
yum -y install epel-release python2-pip
pip install pymongo
# windows(python3)
pip install pymongo

# 连接代码,单实例的连接代码
import pymongo 
client = pymongo.MongoClient( '192.168.1.202', 27017 )
shijiange=client.shijiange
myuser = shijiange.myuser
for item in myuser.find():
  print(item)
    # runfile('C:/Users/Administrator/.spyder-py3/temp.py', wdir='C:/Users/Administrator/.spyder-py3')
    # {'_id': ObjectId('5f5f355cc7bc18dcf8165033'), 'name': 'shijiange1', 'age': 20.0}
    # {'_id': ObjectId('5f5f355cc7bc18dcf8165034'), 'name': 'shijiange2', 'age': 28.0}
    # {'_id': ObjectId('5f5f355cc7bc18dcf8165035'), 'name': 'shijiange3', 'age': 38.0}
    # {'_id': ObjectId('5f5f355cc7bc18dcf8165036'), 'name': 'zhangsan1', 'age': 58.0}
    # {'_id': ObjectId('5f5f355cc7bc18dcf8165037'), 'name': 'zhangsan2', 'age': 68.0}
    # {'_id': ObjectId('5f5f355dc7bc18dcf8165038'), 'name': 'zhangsan3', 'age': 25.0}

# pymongo副本集的连接代码,代码支持自动切换
import pymongo
client = pymongo.MongoClient( ['192.168.1.203:27017', '192.168.1.205:27017'] )
shijiange = client.shijiange
myuser = shijiange.myuser
myvar = {'age':20, 'name': 'shijiange'}
myuser.insert(myvar)
for item in myuser.find():
  print(item)
    # runfile('C:/Users/Administrator/.spyder-py3/temp.py', wdir='C:/Users/Administrator/.spyder-py3')
    # {'_id': ObjectId('5f5f3076d0a7709cefe0eea6'), 'name': 'shijiange1', 'age': 20.0}
    # {'_id': ObjectId('5f5f3076d0a7709cefe0eea7'), 'name': 'shijiange2', 'age': 28.0}
    # {'_id': ObjectId('5f5f3076d0a7709cefe0eea9'), 'name': 'zhangsan1', 'age': 58.0}
    # {'_id': ObjectId('5f5f3076d0a7709cefe0eea8'), 'name': 'shijiange3', 'age': 38.0}
    # {'_id': ObjectId('5f5f3076d0a7709cefe0eeaa'), 'name': 'zhangsan2', 'age': 68.0}
    # {'_id': ObjectId('5f5f307dd0a7709cefe0eeab'), 'name': 'zhangsan3', 'age': 25.0}
    # {'_id': ObjectId('5f5f86463670b531ec7837c6'), 'age': 20, 'name': 'shijiange'}

Python获取MongoDB的状态信息

使用Python去监控mongodb状态,获取mongodb的serverStatus状态信息,一般状态信息需要每个实例都进行监控

# 获取状态信息
import pymongo 
client = pymongo.MongoClient('192.168.1.202',27017)
db = client.admin
serverStatus = db.command('serverStatus')
print(serverStatus)

# 每个状态信息单独打印
import pymongo
client = pymongo.MongoClient('192.168.1.202',27017)
db = client.admin
serverStatus = db.command('serverStatus')
for key,value in serverStatus.items():
  print(key, value)
  print()

# MongoDB建议的监控方向
# connections,连接信息;network ,流量信息;opcounters,增删改查信息
# 状态信息获取
import pymongo 
client = pymongo.MongoClient('192.168.1.202',27017)
db = client.admin
serverStatus = db.command('serverStatus')
print(serverStatus['connections'])
print(serverStatus['network'])
print(serverStatus['opcounters'])

MongoDB分片集群

mongodb分片一般用得比较少,需要较多的服务器,还有三种的角色,一般把mongodb的副本集应用得好就足够用了,可搭建多套mongodb副本集。
mongodb分片技术,mongodb副本集可以解决数据备份、读性能的问题,但由于mongodb副本集是每份数据都一模一样的,无法解决数据量过大问题
mongodb分片技术能够把数据分成两份存储,假如shijiange.myuser里面有1亿条数据,分片能够实现5千万左右存储在data1,5千万左右存储在data2,data1、data2需要使用副本集的形式,预防数据丢失。

MongoDB分片集群角色

mongodb分片集群3种角色

  1. router角色:mongodb的路由,提供入口,使得分片集群对外透明。router不存储数据
  2. configsvr角色:mongodb的配置角色,存储元数据信息。分片集群后端有多份存储,读取数据该去哪个存储上读取,依赖于配置角色。配置角色建议使用副本集
  3. shardsvr角色:mongodb的存储角色,存储真正的数据。建议使用副本集

分片集群角色之间的依赖关系

  1. 当用户通过router角色插入数据时,需要从configsvr知道这份数据插入到哪个节点,然后执行插入动作插入数据到sharedsvr
  2. 当用户通过router角色获取数据时,需要从configsvr知道这份数据是存储在哪个节点,然后再去sharedsvr获取数据

MongoDB分片集群配置

mongodb分片集群的搭建说明:使用同一份mongodb二进制文件,修改对应的配置就能实现分片集群的搭建
mongodb分片集群实战环境搭建说明:

  1. router:使用192.168.1.202来搭建
  2. configsvr:使用192.168.1.203192.168.1.204来搭建
  3. shardsvr:使用192.168.1.205192.168.1.206192.168.1.207192.168.1.208来搭建,192.168.1.205192.168.1.206为一个集群,192.168.1.207192.168.1.208为一个集群

MongoDB分片集群之configsvr

# 192.168.1.203和192.168.1.204
vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
      destination: file
      logAppend: true
      path: /data/mongodb/27017/mongodb.log
    # 存储
    storage:
      dbPath: /data/mongodb/27017/
      journal:
        enabled: true
    # 进程
    processManagement:
      fork: true
    # 网络
    net:
      port: 27017
      bindIp: 0.0.0.0
    # 副本集
    replication:
      replSetName: shijiangeconf
    # 分片角色  
    sharding:
      clusterRole: configsvr
# mongodb配置服务集群的启动跟单例的启动方式一致,都是使用mongod
mongod -f /data/mongodb/27017/mongodb.conf

# 分片集群的配置角色副本集搭建
mongo
config = { _id:"shijiangeconf", 
  configsvr: true,
  members:[
    {_id:0,host:"192.168.1.203:27017"},
    {_id:1,host:"192.168.1.204:27017"}
  ]
}
rs.initiate(config)
# 在SECONDARY机器上查看
rs.secondaryOk() #4.4版本是rs.secondaryOk(),4.0版本是rs.slaveOk()

# 验证是否搭建成功(192.168.1.203、192.168.1.204)
mongo
rs.status()

MongoDB分片集群之router

router最重要的配置:指定configsvr的地址,使用configsvr副本集id(replSetName)/ip:port的方式指定。如果配置多个router,任何一个都能正常的获取数据。
使用mongos启动,而不是mongod

vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
      destination: file
      logAppend: true
      path: /data/mongodb/27017/mongodb.log
    # 进程
    processManagement:
      fork: true
    # 网络
    net:
      port: 27017
      bindIp: 0.0.0.0
    # 分片角色
    sharding:
      configDB: shijiangeconf/192.168.1.203:27017,192.168.1.204:27017
# router的启动
mongos -f /data/mongodb/27017/mongodb.conf

# router的验证:需要等到数据角色搭建完才能够进行验证

MongoDB分片集群之sharedsvr

# 数据角色shijiangedata1:192.168.1.205和192.168.1.206
vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
      destination: file
      logAppend: true
      path: /data/mongodb/29017/mongodb.log
    # 存储
    storage:
      dbPath: /data/mongodb/29017/
      journal:
        enabled: true
    # 进程
    processManagement:
      fork: true
    # 网络
    net:
      port: 27017
      bindIp: 0.0.0.0
    # 副本集
    replication:
      replSetName: shijiangedata1
    # 分片
    sharding:
      clusterRole: shardsvr
# 数据角色shijiangedata2:192.168.1.207和192.168.1.208
vim /data/mongodb/27017/mongodb.conf
    # 日志
    systemLog:
      destination: file
      logAppend: true
      path: /data/mongodb/29017/mongodb.log
    # 存储
    storage:
      dbPath: /data/mongodb/29017/
      journal:
        enabled: true
    # 进程
    processManagement:
      fork: true
    # 网络
    net:
      port: 27017
      bindIp: 0.0.0.0
    # 副本集
    replication:
      replSetName: shijiangedata2
    # 分片
    sharding:
      clusterRole: shardsvr

# 启动4个数据实例
mongod -f /data/mongodb/27017/mongodb.conf

# 数据角色shjiangedata1:192.168.1.205和192.168.1.206
mongo
config = { _id:"shijiangedata1", 
  members:[
    {_id:0,host:"192.168.1.205:27017"},
    {_id:1,host:"192.168.1.206:27017"}
  ]
}
rs.initiate(config)
# 在SECONDARY机器上查看
rs.secondaryOk() #4.4版本是rs.secondaryOk(),4.0版本是rs.slaveOk()

# 数据角色shjiangedata2:192.168.1.207和192.168.1.208
mongo
config = { _id:"shijiangedata2", 
  members:[
    {_id:0,host:"192.168.1.207:27017"},
    {_id:1,host:"192.168.1.208:27017"}
  ]
}
rs.initiate(config)
# 在SECONDARY机器上查看
rs.secondaryOk() #4.4版本是rs.secondaryOk(),4.0版本是rs.slaveOk()

MongoDB分片集群使用

所有的操作都是在route路由角色中

# 分片集群添加数据角色,连接到路由角色里面配置,数据角色为副本集的方式
# 在角色route(192.168.1.202)上执行
mongo
sh.addShard("shijiangedata1/192.168.1.205:27017,192.168.1.206:27017")
sh.addShard("shijiangedata2/192.168.1.207:27017,192.168.1.208:27017")
sh.status()

# 默认添加数据没有分片存储,操作都是在路由角色里面
use shijiange
for(i=1; i<=500;i++){
  db.myuser.insert( {name:'mytest'+i, age:i} )
}
# 此时只有在shijiangedata2(或shijiangedata1)上有数据
db.dropDatabase() #验证完后删除

# 针对某个数据库的某个表使用hash分片存储,分片存储就会同一个colloection分配两个数据角色
use admin  # 此操作只能使用admin用户执行
db.runCommand( { enablesharding :"shijiange"});
db.runCommand( { shardcollection : "shijiange.myuser",key : {_id: "hashed"} } )

# 插入数据校验,分布在两个数据角色上
use shijiange
for(i=1; i<=500;i++){
  db.myuser.insert( {name:'mytest'+i, age:i} )
}
# 此时在shijiangedata2(268条)和shijiangedata1(232条)上各有250条数据