DBA-70-day17

NoSQL-MongoDB运维技术

# NoSQL-MongoDB 运维

# 第一章:MySQL 到 MongoDB快速转型

## 1. MongoDB的简介

![image-20200714174928913](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714174928913.png)

### 1.1 MongoDB趋势及未来展望

![image-20200712214131023](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712214131023.png)

### 1.2 对于MongoDB的认识Q&A

| Q                    | A                                                            |

| -------------------- | ------------------------------------------------------------ |

| 什么是 MongoDB?    | 一个以 JSON 为数据模型的文档数据库                          |

| 为什么叫文档数据库? | 文档来自于“JSON Document”,并非我们一般理解的 PDF,WORD      |

| 谁开发 MongDB?      | 上市公司 MongoDB Inc. ,总部位于美国纽约。                  |

| 主要用途有哪些?    | OLTP\OLAP数据库,类似于 Oracle, MySQL,海量数据处理,数据平台。 |

| 主要特点是什么?    | 无模式或可选。友好的JSON数据模型,开发方便。                |

| MongoDB 是免费的吗? | MongoDB 有两个发布版本:社区版和企业版。企业版基于商业协议,需付费。 |

### 1.3 MongoDB 版本变迁

​ ![image-20200712214832083](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712214832083.png)

### 1.4 MongoDB vs. RDBMS

| 功能        | MongoDB                                  | RDBMS          |

| ------------ | ---------------------------------------- | --------------- |

| 数据模型    | JSON                                    | Relational      |

| 数据库类型  | OLTP/OLAP                                | OLTP/OLAP      |

| CRUD 操作    | MQL/SQL                                  | SQL/SQLX        |

| 高可用      | 原生Replica-Set                          | Cluster、中间件 |

| 横向扩展能力 | 原生MSC                                  | 分片、中间件    |

| 索引支持    | B-Tree、F-text、GIS、multikey、HASH、TTL | B+Tree          |

| 开发难度    | easy                                    | hard            |

| 数据容量    | 无理论上限                              | 千万、亿        |

| 扩展方式    | 垂直扩展+水平扩展                        | 垂直扩展        |

<img src="C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714182132857.png" alt="image-20200714182132857" style="zoom:50%;" />

### 1.5 MongoDB vs. MySQL逻辑结构对比

| MySQL    | MongoDB    |

| -------- | ---------- |

| database | database  |

| table    | collection |

| row      | document  |

![image-20200714175039543](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714175039543.png)

## 2.MongoDB 特色及优势

### 2.1 MongoDB 优势:面向开发者的易用+高效数据库

![image-20200712220144898](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712220144898.png)

#### SQL模型:错综复杂

![image-20200712220544879](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712220544879.png)

#### JSON模型:条理清楚

![image-20200712220619975](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712220619975.png)

![image-20200714174906277](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714174906277.png)

#### 快速响应业务变化:

```

a. 多类型:

同一个Collection中,可以包含不同字段(类型)的文档对象.

b. 更灵活:

线上修改结构,应用与数据库均无须下线。

```

![image-20200712221449231](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712221449231.png)

#### 简洁的开发模式:

```

a. 数据库引擎只需要在一个存储区读写.

b. 反范式、无关联的组织极大优化查询速度.

c. 程序API自然,开发快速.

```

![image-20200712221734097](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712221734097.png)

#### SQL插入数据代码量:

![image-20200712221946591](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712221946591.png)

#### MongoDB 只需要两行代码:

![image-20200712222042384](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712222042384.png)

### 2.2 MongoDB 优势:原生的高可用和横向扩展能力

#### 2.2.1 高可用能力

```

a. Replica Set – 2 to 50 个成员

b. 自恢复

c. 多中心容灾能力

d. 滚动服务 – 最小化服务终端

```

![image-20200712222146248](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712222146248.png)

#### 2.2.2 横向扩展能力

```

a. 需要的时候无缝扩展

b. 应用全透明

c. 多种数据分布策略

d. 轻松支持TB–PB数量级

```

![image-20200712222318802](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200712222318802.png)

### 2.3 MongoDB 技术优势总结

```

a. JSON 结构和对象模型接近,开发代码量低

b. JSON 的动态模型意味着更容易响应新的业务需求

c. 复制集提供99.999%高可用

d. 分片架构支持海量数据和无缝扩容

```

## 3.MongoDB的获取和安装

### 3.1 获取MongoDB

```

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

```

### 3.2安装MongoDB

#### 3.2.0 上传软件并解压

```

[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/

为什么要关闭?

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.

```

#### 3.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

```

### 3.2.2 启动数据库并初始化数据

```

su - mongod

mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork

# 登录mongodb

$ mongo

```

#### 3.2.3 使用配置文件

```

# 普通配置文件应用

vim /mongodb/conf/mongodb.conf

logpath=/mongodb/log/mongodb.log

dbpath=/mongodb/data

port=27017

logappend=true

fork=true

# 关闭mongodb

mongod -f /mongodb/conf/mongodb.conf --shutdown

使用配置文件启动mongodb

mongod -f /mongodb/conf/mongodb.conf

# 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

  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

  bindIp: 10.0.0.21,127.0.0.1


mongod -f /mongodb/conf/mongo.conf --shutdown

mongod -f /mongodb/conf/mongo.conf 

++++++++++++++++++++++

mongodb的关闭方式

mongod -f mongodb.conf  --shutdown

```

#### 3.2.4 用户权限基本管理

##### a . 注意事项

```

用户管理 *****

注意:

--authenticationDatabase

验证库,建立用户时use到的库,在使用用户时,要加上验证库才能登陆。

对于管理员用户,必须在admin下创建.

1. 建用户时,use到的库,就是此用户的验证库

2. 登录时,必须明确指定验证库才能登录

3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库

4. 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的.

```

##### b. 基本语法

```

use 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.0.21/test

-------------

```

##### 角色关系

![image-20200714140327727](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714140327727.png)

##### c. 用户实例

```

(1)--创建超级管理员:管理所有数据库(必须use admin再去创建)

$ mongo

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.0.21/admin

或者

mongo

use admin

db.auth('root','root123')

查看用户:

use admin

db.system.users.find().pretty()

2、创建对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 10.0.0.51/app

4、创建app数据库读写权限的用户并对test数据库具有读权限:

mongo -uroot -proot123 10.0.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.0.51/admin

db.system.users.find().pretty()

6、删除用户(root身份登录,use到验证库)

# mongo -uroot -proot123 10.0.0.51/admin

use app

db.dropUser("app03")

```

## 4. MongoDB 基本CRUD(MQL)

### 4.0 通用方法和帮助获取

```

a.获取帮助

help

> help

db.help()                    help on db methods

db.mycoll.help()            help on collection methods

sh.help()                    sharding helpers

rs.help()                    replica set helpers

db.help();

DB methods:

db.adminCommand(nameOrDocument) - switches to 'admin' db, and runs command [just calls db.runCommand(...)]

db.aggregate([pipeline], {options}) - performs a collectionless aggregation on this database; returns a cursor

db.auth(username, password)

db.cloneDatabase(fromhost) - will only function with MongoDB 4.0 and below

...

> db.t1.help();

DBCollection help

db.t1.find().help() - show DBCursor help

db.t1.bulkWrite( operations, <optional params> ) - bulk execute write operations, optional parameters are: w, wtimeout, j

db.t1.count( query = {}, <optional params> ) - count the number of documents that matches the query, optional parameters are: limit, skip, hint, maxTimeMS

...

db.[TAB][TAB]

db.t1.[TAB][TAB]

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@db01 data]$ mongo -uroot -proot123 10.0.0.51:27017/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")

```

### 4.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()}); }

```

### 4.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/} ) //按正则表达式查找

```

### 4.3 查询条件对照表

| SQL    | MSQL          |

| ------ | -------------- |

| a = 1  | {a: 1}        |

| a <> 1 | {a: {$ne: 1}}  |

| a > 1  | {a: {$gt: 1}}  |

| a >= 1 | {a: {$gte: 1}} |

| a < 1  | {a: {$lt: 1}}  |

| a <= 1 | {a: {$lte: 1}} |

### 4.4 查询逻辑对照表

| SQL            | MSQL                                  |

| --------------- | -------------------------------------- |

| a = 1 AND b = 1 | {a: 1, b: 1}或{$and: [{a: 1}, {b: 1}]} |

| a = 1 OR b = 1  | {$or: [{a: 1}, {b: 1}]}                |

| a IS NULL      | {a: {$exists: false}}                  |

| a IN (1, 2, 3)  | {a: {$in: [1, 2, 3]}}                  |

|                |                                        |

### 4.5 查询逻辑运算符

```

● $lt: 存在并小于

● $lte: 存在并小于等于

● $gt: 存在并大于

● $gte: 存在并大于等于

● $ne: 不存在或存在但不等于

● $in: 存在并在指定数组中

● $nin: 不存在或不在指定数组中

● $or: 匹配两个或多个条件中的一个

● $and: 匹配全部条件

```

### 4.6 使用 find 搜索子文档

```

find 支持使用“field.sub_field”的形式查询子文档。假设有一个文档:

db.fruit.insertOne({

name: "apple",

from: {

country: "China",

province: "Guangdong" }

})

db.fruit.insertOne({ name: "dacong", from: { country: "China", province: "shandong" } })

正确写法:

db.fruit.find( { "from.country" : "China" } )

db.fruit.find( { "from.country" : "China" ,"from.province":"shandong"} )

```

### 4.7 使用 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"}]} )

```

### 4.8 使用 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" }

]

})

db.movies.insertOne( {

"title" : "changcheng",

"filming_locations" : [

{ "city" : "Los Angeles", "state" : "CA", "country" : "USA" },

{ "city" : "Rome", "state" : "Lazio", "country" : "Italy" },

{ "city" : "BJ", "state" : "CN", "country" : "CHN" }

]

})

db.movies.insertOne( {

"title" : "zhenzi",

"filming_locations" : [

{ "city" : "HSD", "state" : "CA", "country" : "USA" },

{ "city" : "dJ", "state" : "JP", "country" : "JPN" },

{ "city" : "sh", "state" : "CN", "country" : "CHN" }

]

})

// 查找城市是 Rome 的记录

db.movies.find({"filming_locations.city": "BJ"})

```

### 4.9 使用 find 搜索数组中的对象

```

在数组中搜索子对象的多个字段时,如果使用 $elemMatch,它表示必须是同一个

子对象满足多个条件。

考虑以下两个查询:

db.getCollection('movies').find({

"filming_locations.city": "dj",

"filming_locations.country": "CHN"

})

db.getCollection('movies').find({

"filming_locations": {

$elemMatch:{"city":"BJ", "country": "CHN"}

}

})

```

### 4.10 控制 find 返回的字段

```

find 可以指定只返回指定的字段;

● _id字段必须明确指明不返回,否则默认返回;

● 在 MongoDB 中我们称这为投影(projection);

● db.movies.find({},{"_id":0, title:1})

```

![image-20200714183012204](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714183012204.png)

### 4.11使用 remove 删除文档

```

remove 命令需要配合查询条件使用;

● 匹配查询条件的的文档会被删除;

● 指定一个空文档条件会删除所有文档;

● 以下示例:

db.testcol.remove( { a : 1 } ) // 删除a 等于1的记录

db.testcol.remove( { a : { $lt : 5 } } ) // 删除a 小于5的记录

db.testcol.remove( { } ) // 删除所有记录

```

### 4.12 使用 update 更新文档

```

Update 操作执行格式:db.<集合>.update(<查询条件>, <更新字段>)

● 以以下数据为例:

db.fruit.insertMany([

{name: "apple"},

{name: "pear"},

{name: "orange"}

])

db.fruit.updateOne({name: "orange"}, {$set: {from: "China"}})

```

![image-20200714141934900](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200714141934900.png)

### 4.13 使用 update 更新文档

```

● 使用 updateOne 表示无论条件匹配多少条记录,始终只更新第一条;

● 使用 updateMany 表示条件匹配多少条就更新多少条;

```

### 4.15 使用 drop 删除集合

```

● 使用 db.<集合>.drop() 来删除一个集合

● 集合中的全部文档都会被删除

● 集合相关的索引也会被删除

db.colToBeDropped.drop()

```

### 4.16 使用 dropDatabase 删除数据库

```

● 使用 db.dropDatabase() 来删除数据库

● 数据库相应文件也会被删除,磁盘空间将被释放

use tempDB

db.dropDatabase()

show collections // No collections

show dbs // The db is gone

```

## 5. 通过python操作mongodb

### 5.1 安装 Python MongoDB 驱动程序

```

在 Python 中使用 MongoDB 之前必须先安装用于访问数据库的驱动程序:

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

yum install -y python3

pip3 install pymongo

+++++++++++++

pip3 install pymongo -i https://pypi.tuna.tsinghua.edu.cn/simple/  #这样快点

+++++++++++++

在 python 交互模式下导入 pymongo,检查驱动是否已正确安装:

import pymongo

pymongo.version

```

### 5.2 创建连接

```

确定 MongoDB 连接串

使用驱动连接到 MongoDB 集群只需要指定 MongoDB 连接字符串即可。其基本格式可

以参考文档: Connection String URI Format 最简单的形式是

mongodb://数据库服务器主机地址:端口号

如:mongodb://127.0.0.1:27017

● 初始化数据库连接

from pymongo import MongoClient

uri = "mongodb://root:root123@10.0.0.51:27017"

client = MongoClient(uri)

client

```

### 5.3 数据库操作:插入数据

```

初始化数据库和集合

db = client["eshop"]

user_coll = db["users"]

插入一条新的用户数据

new_user = {"username": "nina", "password": "xxxx", "email":

"123456@qq.com "}

result = user_coll.insert_one(new_user)

result

```

## 6. MongoDB RS(Replica Set)

### 6.1 复制集的作用

```

MongoDB 复制集的主要意义在于实现服务高可用,它的现实依赖于两个方面的功能:

• 数据写入时将数据迅速复制到另一个独立节点上

• 在接受写入的节点发生故障时自动选举出一个新的替代节点

在实现高可用的同时,复制集实现了其他几个附加作用:

• 数据分发:将数据从一个区域复制到另一个区域,减少另一个区域的读延迟

• 读写分离:不同类型的压力分别在不同的节点上执行

• 异地容灾:在数据中心故障时候快速切换到异地

```

### 6.2 典型复制集结构

```

一个典型的复制集由3个以上具有投票权的节点组成,包括:

• 一个主节点(PRIMARY):接受写入操作和选举时投票

• 两个(或多个)从节点(SECONDARY):复制主节点上的新数据和选举时投票

• Arbiter(投票节点)

```

![image-20200719173016402](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200719173016402.png)

### 6.3 数据是如何复制的

```

当一个修改操作,无论是插入、更新或删除,到达主节点时,它对数据的操作将被记录下来(经过一些必要的转换),这些记录称为 oplog。

从节点通过在主节点上打开一个 tailable 游标不断获取新进入主节点的 oplog,并在自己的数据上回放,以此保持跟主节点的数据一致。

```

![image-20200719173100304](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200719173100304.png)

### 6.4 通过选举完成故障恢复

```

具有投票权的节点之间两两互相发送心跳;

● 当5次心跳未收到时判断为节点失联;

● 如果失联的是主节点,从节点会发起选举,选出新的主节点;

● 如果失联的是从节点则不会产生新的选举;

● 选举基于 RAFT 一致性算法实现,选举成功的必要条件是大多数投票节点存活;

```

![image-20200719173149620](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200719173149620.png)

### 6.5 影响选举的因素

```

整个集群必须有大多数节点存活;被选举为主节点的节点必须:

• 能够与多数节点建立连接

• 具有较新的 oplog

• 具有较高的优先级(如果有配置)

```

### 6.6 常见选项

```

复制集节点有以下常见的选配项:

• 是否具有投票权(v 参数):有则参与投票;

• 优先级(priority 参数):优先级越高的节点越优先成为主节点。优先级为0的节点无法成为主节点;

• 隐藏(hidden 参数):复制数据,但对应用不可见。隐藏节点可以具有投票仅,但优先级必须为0;

• 延迟(slaveDelay 参数):复制 n 秒之前的数据,保持与主节点的时间差。

```

![image-20200719173303341](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200719173303341.png)

![image-20200719173309714](C:\Users\Administrator\Desktop\桌面\mongodb-课件\MongoDB 运维及开发.assets\image-20200719173309714.png)

### 6.7 复制集注意事项

```

● 关于硬件:

• 因为正常的复制集节点都有可能成为主节点,它们的地位是一样的,因此硬件配置上必须一致;

• 为了保证节点不会同时宕机,各节点使用的硬件必须具有独立性。

● 关于软件:

• 复制集各节点软件版本必须一致,以避免出现不可预知的问题。

● 增加节点不会增加系统写性能!

```

### 6.8 Replcation Set配置过程详解

```

1、规划

三个以上的mongodb节点(或多实例)

多实例:

(1)多个端口:28017、28018、28019、28020

(2)多套目录:

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) 多套配置文件

touch /mongodb/28017/conf/mongod.conf

touch /mongodb/28018/conf/mongod.conf

touch /mongodb/28019/conf/mongod.conf

touch /mongodb/28020/conf/mongod.conf

(4)配置文件内容

vi /mongodb/28017/conf/mongod.conf

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

replication:

  oplogSizeMB: 2048

  replSetName: my_repl

\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

chown -R mongod:mongod /mongodb

------------------------------------------------------------

(5)启动多个实例备用

su - mongod

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

2、配置复制集:

(1)1主2从,从库普通从库

config = {_id: 'my_repl', members: [

                          {_id: 0, host: '10.0.0.51:28017'},

                          {_id: 1, host: '10.0.0.51:28018'},

                          {_id: 2, host: '10.0.0.51:28019'}]

          }


rs.initiate(config)

(2)1主1从1个arbiter

config = {_id: 'my_repl', members: [

                          {_id: 0, host: '10.0.0.52:28017'},

                          {_id: 1, host: '10.0.0.52:28018'},

                          {_id: 2, host: '10.0.0.52:28019',"arbiterOnly":true}]

          }


rs.initiate(config)

3、复制集测试:

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();

my_repl:SECONDARY> db.movies.find().pretty();

4、复制集管理操作:

(1)查看复制集状态:

rs.status();    //查看整体复制集状态

rs.isMaster(); // 查看当前是否是主节点

(2)添加删除节点

rs.add("ip:port"); // 新增从节点

rs.addArb("ip:port"); // 新增仲裁节点

rs.remove("ip:port"); // 删除一个节点

注:

添加特殊节点时,

1>可以在搭建过程中设置特殊节点

2>可以通过修改配置的方式将普通从节点设置为特殊节点

/*找到需要改为延迟性同步的数组号*/;

(3)配置延时节点(一般延时节点也配置成hidden)

cfg=rs.conf()

cfg.members[2].priority=0

cfg.members[2].slaveDelay=120

cfg.members[2].hidden=true

rs.reconfig(cfg)   

--------

cfg.members[2].arbiterOnly=true

------------

配置成功后,通过以下命令查询配置后的属性

rs.conf();

5、副本集其他操作命令:

--查看副本集的配置信息

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

```

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345