MongoDB的索引事物和高可用分析

MongoDB

MongoDB是一个基于分布式文件存储的数据库,MongoDB是一个介于关系数据库和非关系数据库(nosql)之间的数据库产品。

MongoDB与MySQL术语对比

MongoDB MySQL
database database
column field
document row
collection table
  • database 数据库,与SQL的数据库(database)概念相同,一个数据库包含多个集合(表)
  • collection集合,相当于SQL中的表(table),一个集合可以存放多个文档(行)。
    不同之处就在于集合的结构(schema)是动态的,不需要预先声明一个严格的表结构。更重要的是,默认情况下 MongoDB并不会对写入的数据做任何schema的校验;

    • document 文档,相当于SQL中的行(row),一个文档由多个字段(列)组成,并采用bson(json)格式表示;
    • field字段,相当于SQL中的列(column),相比普通column的差别在于field的类型可以更加灵活,比如支持嵌套的文档、数组;

MongoDB vs. 关系型数据库

在这里插入图片描述

适用场景

  • 应用不需要事务及复杂 join 支持
  • 新应用,需求会变,数据模型无法确定,想快速迭代开发
  • 应用需要2000-3000以上的读写QPS(更高也可以)
  • 应用需要TB甚至 PB 级别数据存储
  • 应用发展迅速,需要能快速水平扩展
  • 应用要求存储的数据不丢失 应用需要99.999%高可用
  • 应用需要大量的地理位置查询、文本查询

存储引擎和索引

存储引擎

WiredTiger存储引擎之一:基础数据结构分析

索引类型

MongoDB 索引详解(一)

事物

一直以来,"不支持事务" 是 MongoDB 一直被诟病的问题,当然也可以说这是 NoSQL 数据库的一种权衡(放弃事务,追求高性能、高可扩展),但实质上,MongoDB 很早就有事务的概念,但是这个事务只能是针对单文档的,即单个文档的操作是有原子性保证的。
在4.0 版本之后,MongoDB 开始支持多文档的事务:

  • 4.0 版本支持副本集范围的多文档事务;
  • 4.2 版本支持跨分片的多文档事务(基于两阶段提交);

MongoDB 虽然已经在 4.2 开始全面支持了多文档事务,但并不代表大家应该毫无节制地使用它。相反,对事务的使用原则应该是:能不用尽量不用。通过合理地设计文档模型,可以规避绝大部分使用事务的必要性

  • 为什么?事务 = 锁,节点协调,额外开销,性能影响

MongoDB WiredTiger存储引擎支持read-uncommitted、read-committed和snapshot3种事务隔离级别,MongoDB启动时默认选择snapshot隔离。

隔离级别 描述
read-uncommitted 一个事务的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为“脏读(dirty read)”
read-committed 一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的
snapshot 事务开始时,系统会创建一个快照,从已提交的事务中获取行版本数据,如果行版本数据标识的事务尚未提交,则从更早的事务中获取已提交的行版本数据作为其事务开始时的值。类似于 Repeatable Read

事务开发:写操作事务

writeConcern:决定一个写操作落到多少个节点上才算成功。writeConcern 的取值包括:

  • 0:发起写操作,不关心是否成功;
  • 1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功;
  • majority:写操作需要被复制到大多数节点上才算成功。
  • all:写操作需要被复制到全部节点上才算成功。

事务开发:读操作事务

在读取数据的过程中我们需要关注以下两个问题:

  • 从哪里读?
  • 什么样的数据可以读?

第一个问题是是由 readPreference:决定使用哪一个节点来满足正在发起的读请求

  • primary: 只选择主节点;
  • primaryPreferred:优先选择主节点,如果不可用则选择从节点;
  • secondary:只选择从节点;
  • secondaryPreferred:优先选择从节点,如果从节点不可用则选择主节点;
  • nearest:选择最近的节点;

第二个问题则是由 readConcern:决定这个节点上的数据哪些是可读的,类似于关系数据库的隔离级别

  • available:读取所有可用的数据;
  • local:读取所有可用且属于当前分片的数据;
  • majority:读取在大多数节点上提交完成的数据;
  • linearizable:可线性化读取文档;
  • snapshot:读取最近快照中的数据;

事务开发:多文档事务

MongoDB ACID事务支持

在这里插入图片描述

高可用

复制集机制及原理

MongoDB的 复制集类似于MySQL的主从架构,但是又比MySQL的主从架构要强大的多。
复制集的作用:

  • 数据写入时将数据迅速复制到另一个独立节点上
  • 在接受写入的节点发生故障时自动选举出一个新的替代节点

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

  • 数据分发:将数据从一个区域复制到另一个区域,减少另一个区域的读延迟
  • 读写分离:不同类型的压力分别在不同的节点上执行
  • 异地容灾:在数据中心故障时候快速切换到异地

复制集架构

一个典型的复制集由3个以上具有投票权的节点组成,包括:
一个主节点(PRIMARY):接受写入操作和选举时投票
两个(或多个)从节点(SECONDARY):复制主节点上的新数据和选举时投票
不推荐使用 Arbiter(投票节点)
在这里插入图片描述
数据是如何复制的

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

    分片集群架构

    在这里插入图片描述

  • 路由节点 mongos:提供集群入口、转发应用端请求、选择合适数据节点进行读写、合并多个数据节点的返回
  • 配置节点 Config:提供集群元数据存储、分片数据分布的映射
  • 数据节点 mongod:负责存储数据库数据,每个Shard数据分片默认三节点副本集(三节点副本集由Primary节点+1个Secondary节点+1个Arbiter节点构成)、以复制集为单位横向扩展

分片集群特点:应用全透明,无特殊处理、数据自动均衡、动态扩容,无须下线

数据分片策略

Chunks块:MongoDB将分片数据拆分成块。每个分块都有一个基于分片键的上下限范围

基于范围:范围分片能很好的满足『范围查询』的需求,比如想查询x的值在[-75, 25]之间的所有文档,这时mongos直接能将请求路由到Chunk2,就能查询出所有符合条件的文档。

  • 优点:片键范围查询性能好、优化读
  • 缺点:数据分布可能不均匀、容易有热点

基于 Hash:Hash分片是根据用户的shard key计算hash值(64bit整型),根据hash值按照『范围分片』的策略将文档分布到不同的chunk

  • 优点:数据分布均匀,写优化
  • 缺点:范围查询效率低

基于 zone / tag:基于地域去划分

文档参考

你可能感兴趣的:(gomongodb)