MongoDB---基础篇

    1.1 获取MongoDB(6.0以上版本安装教程

                数据备份工具6.0以上版本不在捆绑安装,需要自行下载。

              https://www.mongodb.com/try/download/community

    1.2 上传软件并解压与安装

[root@node01 nosql]# mkdir -p /mongodb && cd /mongodb
[root@node01 nosql]# tar xf mongodb-linux-x86_64-rhel70-4.2.8.tgz
# 关闭THP
root用户下
在vi /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

[root@node01 app]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
[root@node01 app]# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]
其他系统关闭参照官方文档:
https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
为什么要关闭?(提升mongodb的性能)
Transparent Huge Pages (THP) is a Linux memory management system
that reduces the overhead of Translation Lookaside Buffer (TLB)
lookups on machines with large amounts of memory by using larger memory
pages.
However, database workloads often perform poorly with THP,
because they tend to have sparse rather than contiguous memory access
patterns.
You should disable THP on Linux machines to ensure best performance with
MongoDB.

    1.2.1 环境准备

(1)创建所需用户和组
useradd mongod
passwd mongod
(2)创建mongodb所需目录结构
mkdir -p /mongodb/conf
mkdir -p /mongodb/log
mkdir -p /mongodb/data
(3) 修改权限
chown -R mongod:mongod /mongodb
(4) 切换用户并设置环境变量
su - mongod
vi .bash_profile
export PATH=/mongodb/app/bin:$PATH
source .bash_profile

  1.2.2 使用配置文件

 

# 普通配置文件应用
vim /mongodb/conf/mongodb.conf
logpath=/mongodb/log/mongodb.log
dbpath=/mongodb/data
port=27017
logappend=true
fork=true
# YAML 配置文件应用
--
NOTE:
YAML does not support tab characters for indentation: use spaces instead.
--系统日志有关
systemLog:
destination: file
path: "/mongodb/log/mongodb.log" --日志位置
logAppend: true --日志以追加模式记录
--数据存储有关
storage:
journal:
enabled: true   #6.1版本以上不用配置,默认为开启状态
dbPath: "/mongodb/data" --数据路径的位置
-- 进程控制
processManagement:
fork: true --后台守护进程
pidFilePath: <string> --pid文件的位置,一般不用配置,可以去掉这
行,自动生成到data中
--网络配置有关
net:
bindIp: <ip> -- 监听地址,如果不配置这行是监听在0.0.0.0
port: <port> -- 端口号,默认不配置端口号,是27017
-- 安全验证有关配置
security:
authorization: enabled --是否打开用户名密码验证
------------------以下是复制集与分片集群有关----------------------
replication:
oplogSizeMB: <NUM>
replSetName: "<REPSETNAME>"
secondaryIndexPrefetch: "all"
sharding:
clusterRole: <string>
archiveMovedChunks: <boolean>
---for mongos only
replication:
localPingThresholdMs: <int>
sharding:
configDB: <string>
---
.........
++++++++++++++++++++++
YAML例子
vim /mongodb/conf/mongo.conf
systemLog:
   destination: file
   path: "/mongodb/log/mongodb.log"
   logAppend: true
storage:
   journal:
      enabled: true
   dbPath: "/mongodb/data/"
processManagement:
   fork: true
net:
   port: 27017
   bindIpAll: true
   #bindIp: 192.168.47.151 , 127.0.0.1
setParameter:
   enableLocalhostAuthBypass: false

mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf
++++++++++++++++++++++
mongodb的关闭方式
mongod -f mongodb.conf --shutdown

  3.2.3 用户基本管理

  a.基本语法概述

 

 

用户管理 *****
注意:
验证库,建立用户时use到的库,在使用用户时,要加上验证库才能登陆。
对于管理员用户,必须在admin下创建.
1. 建用户时,use到的库,就是此用户的验证库
2. 登录时,必须明确指定验证库才能登录
3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
4. 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的.


use admin
mongo 10.0.51/admin
db.createUser
{
user: "<name>",
pwd: "<cleartext password>",
roles: [
{ role: "<role>",
db: "<database>" } | "<role>",
...
]
}
基本语法说明:
user:用户名
pwd:密码
roles:
    role:角色名
    db:作用对象
role:root, readWrite,read  
验证数据库:
mongo -u test -p 123 10.0.51/test
  

   b. 用户实例

(1)--创建超级管理员:管理所有数据库(必须use admin再去创建)
db.createUser(
{
    user: "root",
    pwd: "root123",
    roles: [ { role: "root", db: "admin" } ]
}
)

验证用户
db.auth('root','root123')
配置文件中,加入以下配置
security:
   authorization: enabled

重启mongodb
mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf
登录验证
mongo -uroot -proot123 admin
mongo -uroot -proot123 10.0.51/admin

查看用户:
use admin
db.system.users.find().pretty()
2、创建库管理用户
mongo -uroot -proot123 admin
use app
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [ { role: "dbAdmin", db: "app" } ]
}
)
db.auth('admin','admin')
登录测试
mongo -uadmin -padmin 10.0.51/app
3、创建对app数据库,读、写权限的用户app01:
(1)超级管理员用户登陆
mongo -uroot -proot123 admin
(2)选择一个验证库
use app
(3)创建用户
db.createUser(
{
user: "app01",
pwd: "app01",
roles: [ { role: "readWrite" , db: "app" } ]
}
)
mongo -uapp01 -papp01 app
4、创建app数据库读写权限的用户并对test数据库具有读权限:
mongo -uroot -proot123 10.0.51/admin
use app
db.createUser(
{
user: "app03",
pwd: "app03",
roles: [ { role: "readWrite", db: "app" },
{ role: "read", db: "test" }
]
}
)
5、查询mongodb中的用户信息
mongo -uroot -proot123 10.0.51/admin
db.system.users.find().pretty()
6、删除用户(root身份登录,use到验证库)
# mongo -uroot -proot123 10.0.51/admin
use app
db.dropUser("admin")

 

 

  2.MongoDB 基本CRUD

        2.0 通用方法和帮助获取

b. 常用操作
//查看当前db版本
test> db.version()
//显示当前数据库
test> db
> db.getName()
// 查询所有数据库
test> show dbs
//切换数据库
> use local
// 显示当前数据库状态
查看local数据
test> use local
local> db.stats()
查看当前数据库的连接机器地址
> db.getMongo()
// 指定数据库进行连接:(默认连接本机test数据库)
# mongo 192.168.1.24/admin
[mongod@mongodb ~]$ mongo 192.168.1.24/admin
c. 库和表的操作
// 建库
use test
// 删除
> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
// 创建集合(表)
方法1:
admin> use app
app> db.createCollection('a')
app> db.createCollection('b')
方法2:当插入一个文档的时候,一个集合就会自动创建。
admin> use app
switched to db app
app> db.c.insert({username:"mongodb"})
WriteResult({ "nInserted" : 1 })
app> show collections
app> db.c.find()
{ "_id" : ObjectId("5743c9a9bf72d9f7b524713d"), "username" : "mongodb" }
// 删除集合
app> use app
switched to db app
app> db.log.drop() //删除集合
// 重命名集合(表名)
app> db.log.renameCollection("log1")

    2.1 使用 insert 完成插入操作

操作格式:
db.<集合>.insertOne(<JSON对象>)
db.<集合>.insertMany([<JSON 1>, <JSON 2>, …<JSON n>])
示例:
db.fruit.insertOne({name: "apple"})
db.fruit.insertMany([
{name: "apple"},
{name: "pear"},
{name: "orange"}
])
批量插入数据:
for(i=0;i<10000;i++){
db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()}); }

    2.2 使用 find 查询文档

# 关于 find:
find 是 MongoDB 中查询数据的基本指令,相当于 SQL 中的 SELECT 。
find 返回的是游标。
# find 示例:
db.movies.find( { "year" : 1975 } ) //单条件查询
db.movies.find( { "year" : 1989, "title" : "Batman" } ) //多条件and查询
db.movies.find( { $and : [ {"title" : "Batman"}, { "category" : "action" }] }) // and的另一种形式
db.movies.find( { $or: [{"year" : 1989}, {"title" : "Batman"}] } ) //多条件or查询
db.movies.find( { "title" : /^B/} ) //按正则表达式查找

    2.3查询条件对照表(msql为mongo)

     2.4 查询逻辑对照表

     2.5 使用 find 搜索子文档

find 支持使用“field.sub_field”的形式查询子文档。假设有一个文档:
db.fruit.insertOne({
name: "apple",
from: {
country: "China",
province: "Guangdong" }
})
正确写法:
db.fruit.find( { "from.country" : "China" } )

    2.6 使用 find 搜索数组

find 支持对数组中的元素进行搜索。假设有一个文档:
db.fruit.insert([
{ "name" : "Apple", color: ["red", "green" ] },
{ "name" : "Mango", color: ["yellow", "green"] }
])
查看单个条件:
db.fruit.find({color: "red"})
查询多个条件:
db.fruit.find({$or: [{color: "red"}, {color: "yellow"}]} )

    2.7 使用 find 搜索数组中的对象

考虑以下文档,在其中搜索
db.movies.insertOne( {
"title" : "Raiders of the Lost Ark",
"filming_locations" : [
{ "city" : "Los Angeles", "state" : "CA", "country" : "USA" },
{ "city" : "Rome", "state" : "Lazio", "country" : "Italy" },
{ "city" : "Florence", "state" : "SC", "country" : "USA" }
]
})
// 查找城市是 Rome 的记录
db.movies.find({"filming_locations.city": "Rome"})


在数组中搜索子对象的多个字段时,如果使用 $elemMatch,它表示必须是同一个
子对象满足多个条件。
考虑以下两个查询:
db.getCollection('movies').find({
"filming_locations.city": "Rome",
"filming_locations.country": "USA"
})
db.movies.insertOne( {
"title" : "11111",
"filming_locations" : [
{ "city" : "bj", "state" : "CA", "country" : "CHN" },
{ "city" : "Rome", "state" : "Lazio", "country" : "Italy" },
{ "city" : "tlp", "state" : "SC", "country" : "USA" }
]
})
db.getCollection('movies').find({
"filming_locations": {
$elemMatch:{"city":"bj", "country": "CHN"}
}
})

    2.8 使用 remove 删除文档

remove 命令需要配合查询条件使用;
● 匹配查询条件的的文档会被删除;
● 指定一个空文档条件会删除所有文档;
● 以下示例:
db.testcol.remove( { a : 1 } ) // 删除a 等于1的记录
db.testcol.remove( { a : { $lt : 5 } } ) // 删除a 小于5的记录
db.testcol.remove( { } ) // 删除所有记录
db.testcol.remove() //报错

    2.9 使用 update 更新文档

Update 操作执行格式:db.<集合>.update(<查询条件>, <更新字段>)
● 以以下数据为例:
db.fruit.insertMany([
{name: "apple"},
{name: "pear"},
{name: "orange"}
])
db.fruit.updateOne({name: "apple"}, {$set: {from: "China"}})


● 使用 updateOne 表示无论条件匹配多少条记录,始终只更新第一条;
● 使用 updateMany 表示条件匹配多少条就更新多少条;
● updateOne/updateMany 方法要求更新条件部分必须具有以下之一,否则将报错:
• $set/$unset
• $push/$pushAll/$pop
• $pull/$pullAll
• $addToSet
● // 报错
db.fruit.updateOne({name: "apple"}, {from: "China"})

● $push: 增加一个对象到数组底部
● $pushAll: 增加多个对象到数组底部
● $pop: 从数组底部删除一个对象
● $pull: 如果匹配指定的值,从数组中删除相应的对象
● $pullAll: 如果匹配任意的值,从数据中删除相应的对象
● $addToSet: 如果不存在则增加一个值到数组

  3. MongoDB RS(Replica Set)

    3.1 复制集的作用

 

MongoDB 复制集的主要意义在于实现服务高可用,它的现实依赖于两个方面的功能:
• 数据写入时将数据迅速复制到另一个独立节点上
• 在接受写入的节点发生故障时自动选举出一个新的替代节点
在实现高可用的同时,复制集实现了其他几个附加作用:
• 数据分发:将数据从一个区域复制到另一个区域,减少另一个区域的读延迟
• 读写分离:不同类型的压力分别在不同的节点上执行
• 异地容灾:在数据中心故障时候快速切换到异地

 

        3.2 典型复制集结构

 

一个典型的复制集由3个以上具有投票权的节点组成,包括:
• 一个主节点(PRIMARY):接受写入操作和选举时投票
• 两个(或多个)从节点(SECONDARY):复制主节点上的新数据和选举时投票
• Arbiter(投票节点)

 

  

 

 

 

      3.3 数据是如何复制的

 

当一个修改操作,无论是插入、更新或删除,到达主节点时,它对数据的操作将被记录下来(经过一些必
要的转换),这些记录称为 oplog。
从节点通过在主节点上打开一个 tailable 游标不断获取新进入主节点的 oplog,并在自己的数据上
回放,以此保持跟主节点的数据一致。

 

        3.4 通过选举完成故障恢复

 

 

具有投票权的节点之间两两互相发送心跳;
● 当5次心跳未收到时判断为节点失联;
● 如果失联的是主节点,从节点会发起选举,选出新的主节点;
● 如果失联的是从节点则不会产生新的选举;
● 选举基于 RAFT 一致性算法实现,选举成功的必要条件是大多数投票节点存活;

 

        

      3.5 常见选项

 

 

复制集节点有以下常见的选配项:
• 是否具有投票权(v 参数):有则参与投票;
• 优先级(priority 参数):优先级越高的节点越优先成为主节点。优先级为0的节点无法成为主节
点;
• 隐藏(hidden 参数):复制数据,但对应用不可见。隐藏节点可以具有投票仅,但优先级必须为0;
• 延迟(slaveDelay 参数):复制 n 秒之前的数据,保持与主节点的时间差。

 

       3.6 Replcation Set配置过程详解

      a.环境准备

 

cat > /mongodb/28017/conf/mongod.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/28017/log/mongodb.log
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true    #选项使得每个数据库都存储在单独的文件夹中,这样可以更好地管理数据文件。
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1  #用于设置WiredTiger存储引擎的缓存大小。
      directoryForIndexes: true  #是否将索引也按数据库名单独存储 
    collectionConfig:
      blockCompressor: zlib  #压缩方式 ,默认 snappy,这里选择 none 或者 zlib 
    indexConfig:
      prefixCompression: true  #默认为true,即使用前缀压缩索引数据。
processManagement:
  fork: true      #后台运行
net:
  port: 28017
  bindIpAll: true
replication:
  oplogSizeMB: 2048
  replSetName: my_repl
EOF

 

三个以上的mongodb节点(或多实例)
多实例:
(1)多个端口:28017、28018、28019、28020
(2)多套目录:
su - mongod
mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log
mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log
mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log
mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log
(3)配置文件内容准备
cat > /mongodb/28017/conf/mongod.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/28017/log/mongodb.log
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
processManagement:
  fork: true
net:
  port: 28017
  bindIpAll: true
replication:
  oplogSizeMB: 2048
  replSetName: my_repl
EOF

\cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/
sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i
------------------------------------------------------------
(4)启动多个实例备用
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf

  b.. 配置复制集:

(1)1主2从,从库普通从库(PSS)
config = {_id: 'my_repl', members: [
        {_id: 0, host: '127.0.0.1:28017'},
        {_id: 1, host: '127.0.0.1:28018'},
        {_id: 2, host: '127.0.0.1:28019'}]
}
rs.initiate(config)

(2)1主1从1个arbiter(PSA)
config = {_id: 'my_repl', members: [
        {_id: 0, host: '127.0.0.1:28017'},
        {_id: 1, host: '127.0.0.1:28018'},
        {_id: 2, host: '127.0.0.1:28019',"arbiterOnly":true}]
}
rs.initiate(config)

  c.复制集测试:

my_repl:PRIMARY> db.movies.insert([ { "title" : "Jaws", "year" : 1975,
"imdb_rating" : 8.1 },
... { "title" : "Batman", "year" : 1989, "imdb_rating" : 7.6 },
... ] );
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
my_repl:SECONDARY> db.movies.find().pretty();
注:在mongodb复制集当中,默认从库不允许读写。
rs.slaveOk();【新版本中用rs.secondaryOk()】
my_repl:SECONDARY> db.movies.find().pretty();

  d. 复制集管理操作:

(1)查看复制集状态:
rs.status(); //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
(2)添加删除节点
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点
rs.remove("ip:port"); // 删除一个节点
(3)特殊从节点的配置
• 优先级(priority 参数:0-1000):
优先级越高的节点越优先成为主节点。
优先级为0的节点无法成为主节点;
• 隐藏(hidden 参数):复制数据,但对应用不可见。隐藏节点可以具有投票仅,但优先级必须为
0;
• 延迟(slaveDelay 参数):复制 n 秒之前的数据,保持与主节点的时间差。
配置延时节点(一般延时节点也配置成hidden)
cfg=rs.conf()
cfg.members[1].priority=0
cfg.members[1].slaveDelay=120
cfg.members[1].hidden=true
rs.reconfig(cfg)
改回来:
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].slaveDelay=0
cfg.members[2].hidden=0
cfg.members[2].votes=0
rs.reconfig(cfg)
配置成功后,通过以下命令查询配置后的属性
rs.conf();

e.其他常规操作  

 

--查看副本集的配置信息
admin> rs.config()
--查看副本集各成员的状态
admin> rs.status()
--副本集角色切换(不要人为顺便操作,有风险)
admin> rs.stepDown()
注:
admin> rs.freeze(300) //锁定从,使其不会转变成主库
freeze()和stepDown单位都是秒。
--设置副本节点可读:在副本节点执行
admin> rs.slaveOk()
eg:
admin> use app
switched to db app
app> db.createCollection('a')
{ "ok" : 0, "errmsg" : "not master", "code" : 10107 }
--查看副本节点
admin> rs.printSlaveReplicationInfo()
source: 192.168.1.22:27017
  syncedTo: Thu May 26 2016 10:28:56 GMT+0800 (CST)
  0 secs (0 hrs) behind the primary

  

posted on 2023-02-06 22:19  leiyunfeng  阅读(2)  评论(0编辑  收藏  举报