安装
官网下载【linux】:www.mongodb.com/try/downloa…
官方可视化:www.mongodb.com/try/downloa…
# 配置环境变量
vim /etc/profile
export = /data/mongodb/bin:$PATH
source /etc/profile
启动
先启动 /bin 目录下的 mongod mongo 服务
客户端连接的时候 如果报错:修改配置文件,如没有则新建配置文件 mongod.conf 添加
port=27017 #端口
dbpath= /usr/mongodb/db #数据库存文件存放目录
logpath= /usr/mongodb/log/mongodb.log #日志文件存放路径
logappend=true #使用追加的方式写日志
fork=true #以守护进程的方式运行,创建服务器进程
maxConns=100 #最大同时连接数
noauth=true #不启用验证
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0 #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
启动:mongod -f /***/mongod.conf
常用命令
show dbs // 查看所有数据库
use XXX // 切换到XXX数据库
show collections // 显示所有集合(表)
db.xxx.find() // 显示XXX的所有数据
db.fruit.insertOne({name:"apple",from:{country: "China",province: "Guangdon"}})
db.fruit.find({"from.country": "China"})
db.fruit.insert([{"name":"Apple",color:["red","green"]},{"name":"Mango",color:["yellow","green"]}])
db.fruit.find({$or:[{color:"red"},{color:"yellow"}]})
db.fruit.find({$and:[{color:"red"},{color:"yellow"}]})
db.fruit.find({},{_id:0,"name":1}) // 只显示name字段
db.fruit.remove() // 清空
db.fruit.insertMany([{"name":"apple"},{"name":"pear"},{"name":"orange"}])
db.fruit.updateOne({"name":"apple"},{$set:{from:"China"}})
-- $push: 增加一个对象到数组底部
$pushAll:增加多个对象到数组底部
$pop: 从数组底部删除一个对象
$pull:如果匹配指定的值,从该数组中删除相应的对象
$pullAll:如果匹配任意的值,从数据中删除相应的对象
$addToSet:如果不存在则增加一个值到数组
db.fruit.find().pretty() // 格式化查看
db.xxx.drop() // 删除xxx集合s
db.dropDatabase() //删库跑路
python 使用mongodb 练习
import pymongo
from pymongo import MongoClient
uri = "mongodb://192.168.32.85:27017"
client = MongoClient(uri)
db = client["eshop"]
user_coll = db["users"]
new_user = {"username":"nina","password":"xxxx","email":"123456@qq.com"}
result = user_coll.insert_one(new_user)
print (result)
result = user_coll.update_one({"username":"nina"},{"$set":{"phone":"123456789"}})
print (result)
聚合查询
$math //过滤 == where
$project // 投影 AS
$sort //排序 order by
$group // 分组 group by
$skip/$limit //结果限制 SKIP/LIMIT
$lookup //左外连接 left outer join
db.orders.aggregate([{$match:{status:"completed",orderDate:{$gte:ISODate("2019-01-01"),$lt:ISODate("2019-04-01")}}},{$group:{_id:null,total:{$sum:"$total"},shippingFee:{$sum:"$shippingFee"},count:{$sum:1}}},{$project:{grandTotal:{$add:["$total","$shippingFee"]},count:1,_id:1}}])
mongo复制集 高可用
-
数据如何复制的
- 当有修改的操作,会记录到oplog日志里面
- 从节点在主节点上打开一个游标不断获取新进入主节点的oplog,写到自己的节点
-
选举
- 具有投票权的节点之间两两互相发送心跳(默认是两秒)
- 当5次心跳未收到时判断为节点失联
- 如果是失联的是主节点,从节点会发起选举,选出新的主节点
- 如果是失联的是从节点,不会产生新的选举
- 选举基于RAFT一致性算法实现,选举成功的必要条件是大多数投票节点存活
- 复制集中最多可以有50个节点,但具有投票权的节点最多7个
-
影响选举的因素
-
整个集群必须有大多数节点存活
-
被选举为主节点的节点必须:
- 能够与多数节点建立链接
- 具有较新3的oplog
- 具有较高的优先级(如果有设置)
-
-
复制节点常见的选配项
- 是否具有投票权(v参数):有则参与投票
- 优先级(priority参数):优先级越高的节点越优先成为主节点。优先级为0的系欸但无法成为主节点
- 隐藏(hidden参数):复制数据,但对应用不可见。隐藏节点可以具有投票权,但优先级必须为0
- 延迟(slaveDelay参数):复制N秒之前的数据,保持与主机点的时间差
复制集群搭建--单台服务器
mkdir /data/db{1,2,3}
vi /data/db1/mongod.conf
systemLog:
destination: file
path: /data/db2/mongod.log
logAppend: true
storage:
dbPath: /data/db2
net:
bindIp: 0.0.0.0
port: 28018
replication:
replSetName: rs0
processManagement:
fork: true
mongod -f /data/db1/mongod.conf # 分别启动
mongo localhost:28017 #启动一个节点
rs.initiate() # 初始化复制集
rs.add("hostname:28018") # 添加节点
#从节点读数据
rs.slaveOk();
常用模式
分桶
记录飞机飞行位置,每分钟一次的记录可以改为每个小时一个记录,记录里面数组记录每分钟的记录
行专列
可以利用索引查询统计
定时执行
预聚合
事务开发 写操作
writeConcern 决定一个写操作落到多少个节点上才算成功。默认为 1
- 0:发起写操作,不关心是否成功
- 1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功
- majority:写操作需要被复制到大多数节点上才算成功
- all 所有节点
发起写操作的程序将阻塞到写操作到达指定的节点数为止
journal 定义如何才算成功:
- true:写操作落到journal 文件中才算成功
- false:写操作到达内存计算做成功
db.xxx.insert({count:2},{writeConcern:{w:3,wtimeout:3000}}) # 写到三个节点才算成功 3000毫秒失败直接返回
事务开发 读操作
readPreference 决定使用哪一个节点来满足正在发起的读请求
- primary:只选择主节点
- primaryPreferred:优先选择主节点,如果不可用则选择从节点
- secondary:只选择从节点
- secondaryPreferred:优先选择从节点,如果从节点不可用则选择主节点
- nearest:选择最近的节点
readConcern 决定这个节点上的数据那些是可读的,类似于数据库的隔离级别
- available:读取所有可用的数据
- local:读取所有可用且属于当前分片的数据 默认
- majority:读取在大多数节点上提交完成的数据
- linearizable:可线性化读取文档 读取多数节点上最新的值 太慢
- snapshot:读取最近快照中的数据
readConcern:majority 与脏读
MongoDb中的回滚:
- 写操作到达大多数节点之前都是不安全的,一旦主节点崩溃,而从节点还没复制到该次操作,刚才的写操作就丢失了
- 把一次写操作视为一个事务,从事务的角度,可以认为事务被回滚了
所以从分布式系统的角度来看,事务的提交被提升到了分布式集群的多个节点级别的“提交”,而不再是单个节点上的“提交”
在可能发生回滚的前提下考虑脏读问题:
- 如果在一次写操作到达大多数节点前读取了这个写操作,然后因为系统故障该操作回滚了,则发生了脏读问题
使用{readConcern:“majority”} 可以有效避免脏读
事务开发 多文档事务
- 事务完成前,事务外的操作对该事物所做的修改不可访问
- 如果事务内使用{readConcern:“snapshot”},则可以达到可重复读 Repeatable Read
分片
最多1024片
集群解刨
-
路由节点mongos
提供集群单一入口、转发应用端请求、选择合适数据节点进行读写、合并多个数据节点的返回。无状态,建议最少2个
-
配置节点 mongod
提供集群元数据存储分片数据分布的映射 shard存放分片的范围 0-10000,mongos会加载到内存 去比对
-
数据节点 mongod
以复制集为单位,横向扩展,最大1024分片,分片之间数据不重复,所有分片在一起才可以完整工作
数据分布方式
-
基于范围
-
优势
- 片键范围查询性能好
- 优化读
-
劣势
- 数据分布可能不均匀
- 容易有热点
-
-
基于Hash
-
优势
- 数据分布均匀,写优化
-
劣势
- 范围查询效率低
-
适用:日志,物联网等高并发场景
-
-
基于 zone / tag
分片集群设计
-
合理的架构-分片大小
分片的基本标准:
- 关于数据:数据量不超过3TB,尽可能保持在2TB一个片
- 关于索引:常用索引必须容纳进内存
-
需要多少个分片
A= 所需存储总量 / 但服务器可挂载容量 8TB /2TB = 4
B = 工作集大小 / 单服务器内存容量 400GB / (256G*0.6) = 3
C = 并发量总数 / (单服务器并发量 * 0.7) 30000 / (9000*0.7) = 6
分片数量 = max(A,B,C) = 6
-
正确的姿势,各种概念由小到大
- 片键shard key:文档中的一个或多个字段
- 文档doc:包含shard key的一行数据
- 块Chunk:包含N个文档
- 分片Shard:包含n个chunk
- 集群cluster:包含n个分片
-
正确的姿势,选择合适片键,影响片键效率的主要因素
-
取值基数 - 选择基数大的片键
对于小基数的片键
因为备选值有限,那么块的总数量就有限
随着数据增多,块的大小会越来越大
太大的块,会导致水平扩展时移动块会非常困难
-
取值分布 - 选择分布均匀的片键
对于分布不均匀的片键
造成某些块的数据量急剧增大
这些块压力随之增大
数据均衡以chunk为单位,所以系统无能为力
-
分散写,集中读
-
被尽可能多的业务场景用到 - 定向性好
4个分片的集群,希望读某条特定的数据,如果用片键作为条件查询,mongos可以直接定位到具体的分片
如果不用片键,mongos需要把查询发到4个分片,等最后一个分片响应,mongos才能响应应用端
-
避免单调递增或递减的片键
-
MongoDb的备份
-
MongoDb的备份机制分为:
- 延迟节点备份
- 全量备份 + oplog 增量
-
最常见的全量备份方式:
- mongodump
- 复制数据文件
- 文件系统快照
MongoDB 安全
默认是没有启用鉴权
索引
组合索引
ESR原则
- 精确(Equal)匹配的字段放最前面
- 排序(Sort)条件放中间
- 范围(Range)匹配的字段放最后面
容灾级别
无备源中心
没有灾难恢复能力,只在本地进行数据备份
本地备份 + 异地保存
- 本地将关键数据备份,然后送到异地保存,灾难发生后,安预定数据恢复程序恢复系统和数据
双中心主备模式
在异地建立一个热备份点,通过网络进行数据备份。当出现灾难时,备份站点接替主站点的业务,维护业务连续性
双中心双活
在相隔较远的地方分别建立两个数据中心,进行相互数据备份。当某个数据中心发生灾难时,另一个数据中心接替其工作任务
双中心双活+异地热备 = 两地三中心
在同城分别建立两个数据中心,进行相互数据备份。当该城市的2个中心同时不可用,快速切换到异地
两地三中心需要考量点
- 节点数量建议5个,2+2+1 模式
- 主数据中心的两个节点要设置高一点的优先级,减少跨中心换主节点
- 同城双中心之间的网络要保证低延迟和频宽,满足writeConcern:majority 的双中心写需求
- 使用retryable writes and retryable reads 老保证零下线时间 4.2 默认
- 用户需要自行处理好业务层的双中心切换
上线前环境检查
最常见的需要调整的参数:
- 禁用NUMA,否则在某些情况下会引起突发大量swap交换
- 禁用transparent huge page,否则会影响数据库效率
- tcp_keepalive_time 调整为120秒,避免一些网络问题
- ulimit-n,避免打开文件句柄不足的情况
- 关闭atime,提高数据文件访问效率
MongoDB数据库定位
- OLTP数据库
- 原则上Oracle和MySQL能做的事情,MongoDB都能做
- 优点:横向扩展能力,数据量或并发量增加时候架构可以自动扩展
- 优点:灵活模型,适合迭代开发,数据模型多变场景
- 优点:JSON数据结构,适合微服务/RSET API
cloud.tapdata.net