mongodb 学习记录

173 阅读9分钟

安装

官网下载【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复制集 高可用

  1. 数据如何复制的

    • 当有修改的操作,会记录到oplog日志里面
    • 从节点在主节点上打开一个游标不断获取新进入主节点的oplog,写到自己的节点
  2. 选举

    • 具有投票权的节点之间两两互相发送心跳(默认是两秒)
    • 当5次心跳未收到时判断为节点失联
    • 如果是失联的是主节点,从节点会发起选举,选出新的主节点
    • 如果是失联的是从节点,不会产生新的选举
    • 选举基于RAFT一致性算法实现,选举成功的必要条件是大多数投票节点存活
    • 复制集中最多可以有50个节点,但具有投票权的节点最多7个
  3. 影响选举的因素

    • 整个集群必须有大多数节点存活

    • 被选举为主节点的节点必须:

      • 能够与多数节点建立链接
      • 具有较新3的oplog
      • 具有较高的优先级(如果有设置)
  4. 复制节点常见的选配项

    • 是否具有投票权(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:3wtimeout: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

分片集群设计

  1. 合理的架构-分片大小

    分片的基本标准:

    • 关于数据:数据量不超过3TB,尽可能保持在2TB一个片
    • 关于索引:常用索引必须容纳进内存
  2. 需要多少个分片

    A= 所需存储总量 / 但服务器可挂载容量 8TB /2TB = 4

    B = 工作集大小 / 单服务器内存容量 400GB / (256G*0.6) = 3

    C = 并发量总数 / (单服务器并发量 * 0.7) 30000 / (9000*0.7) = 6

    分片数量 = max(A,B,C) = 6

  3. 正确的姿势,各种概念由小到大

    • 片键shard key:文档中的一个或多个字段
    • 文档doc:包含shard key的一行数据
    • 块Chunk:包含N个文档
    • 分片Shard:包含n个chunk
    • 集群cluster:包含n个分片
  4. 正确的姿势,选择合适片键,影响片键效率的主要因素

    • 取值基数 - 选择基数大的片键

      对于小基数的片键

      因为备选值有限,那么块的总数量就有限

      随着数据增多,块的大小会越来越大

      太大的块,会导致水平扩展时移动块会非常困难

    • 取值分布 - 选择分布均匀的片键

      对于分布不均匀的片键

      造成某些块的数据量急剧增大

      这些块压力随之增大

      数据均衡以chunk为单位,所以系统无能为力

    • 分散写,集中读

    • 被尽可能多的业务场景用到 - 定向性好

      4个分片的集群,希望读某条特定的数据,如果用片键作为条件查询,mongos可以直接定位到具体的分片

      如果不用片键,mongos需要把查询发到4个分片,等最后一个分片响应,mongos才能响应应用端

    • 避免单调递增或递减的片键

MongoDb的备份

  1. MongoDb的备份机制分为:

    • 延迟节点备份
    • 全量备份 + oplog 增量
  2. 最常见的全量备份方式:

    • mongodump
    • 复制数据文件
    • 文件系统快照

MongoDB 安全

默认是没有启用鉴权

索引

组合索引

ESR原则

  • 精确(Equal)匹配的字段放最前面
  • 排序(Sort)条件放中间
  • 范围(Range)匹配的字段放最后面

容灾级别

无备源中心

没有灾难恢复能力,只在本地进行数据备份

本地备份 + 异地保存

  1. 本地将关键数据备份,然后送到异地保存,灾难发生后,安预定数据恢复程序恢复系统和数据

双中心主备模式

在异地建立一个热备份点,通过网络进行数据备份。当出现灾难时,备份站点接替主站点的业务,维护业务连续性

双中心双活

在相隔较远的地方分别建立两个数据中心,进行相互数据备份。当某个数据中心发生灾难时,另一个数据中心接替其工作任务

双中心双活+异地热备 = 两地三中心

在同城分别建立两个数据中心,进行相互数据备份。当该城市的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