• MongoDB 小结


    MongoDB & 关系型数据库

    在这里插入图片描述

    MongoDB 的读操作事务

    在读取数据的过程中,需要关注以下两个问题。

    • 从哪里读?—— 关注数据节点的位置
    • 读什么数据?—— 关注数据的隔离性

    第一个问题是由 readPreference 来解决;第二个问题则是由 readConcern 来解决。

    什么是 readPreference?

    在这里插入图片描述

    MongoDB 是分布式的架构,在最小的部署下,它必须是一个“主-从-从”一主二从的三个节点的架构,如果涉及到分片,那么可能会有几十个节点。数据分布在这些节点上,从哪个节点读取数据,就是一个非常大的学问。

    readPreference 决定使用哪一个节点来满足正在发起的读请求,它的可选值有如下几种。

    • primary

    只选择主节点(默认值)。

    • primaryPreferred

    优先选择主节点,如果不可用则选择从节点。

    • secondaryPreferred

    优先选择从节点,如果从节点不可用则选择主节点

    • nearest

    选择最近的节点(根据 ping time 来决定)

    readPreference 的使用场景

    • 用户下单后马上跳转到订单详情页 —— primary/primaryPreferred

    因为此时从节点可能还没有复制到新订单。

    • 用户查询历史订单 —— secondary/secondaryPreferred

    因为查询历史订单,通常对时效性没有太高的要求。

    • 生成报表 —— secondary

    因为报表对时效性要求不高,但对资源的需求大,可以在从节点上单独处理,避免对线上用户造成影响。

    • 将用户上传的图片分发到各地,让其他用户可以就近读取 —— nearest

    因为这样每个地区的应用都可以选择最近的节点来读取数据。

    readPreference & Tag

    如上所述,readPreference 可以设置固定的节点角色(主节点/从节点),但有些情况下,可能并没有固定的节点角色,或者需要定向指向某个或某些节点,这时可以考虑使用 Tag。

    readPreference 只能控制使用一类节点,Tag 则可以将节点选择控制到一个或几个节点。

    假设有如下场景:一个拥有 5 个节点的复制集,3 个节点硬件较好,专用于服务线上用户;2 个节点硬件较差,专用于生成报表。

    这时可以使用 Tag 来进行区分控制:为 3 个较好的节点打上 { purpose: “online” };为 2 个较差的节点打上 { purpose: “analyse” },在线应用读取时指定 online,报表读取时指定 analyse。

    在这里插入图片描述

    readPreference 的配置

    • 通过 MongoDB 的连接串参数

    mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=rs&readPreference=secondary

    • 通过 MongoDB 的驱动程序 API

    MongoCollection.withReadPreference(ReadPreference readPref)

    • Mongo Shell

    db.collection.find({}).readPref(“secondary”)

    readPreference 的注意事项

    • 指定 readPreference 时也应注意高可用问题。例如将 readPreference 指定为 primary,在发生故障转移不存在 primary 时,将没有节点可读,如果业务允许,应选择 primaryPreference
    • 使用 Tag 时也会有上述问题,如果只有一个节点拥有一个特定 Tag,在这个节点失效时,将无节点可读
      • 如果报表使用的节点失效,即使不生成报表,通常也不希望将报表负载转移到其他节点上,此时只有一个节点有报表 Tag 是合理的
      • 如果线上节点失效,通常希望有替代节点,所以应该保持有多个节点有相同的 Tag
    • Tag 有时需要综合考虑优先级和选举权,例如做报表的节点通常不会希望它成为主节点,则优先级应设为 0

    MongoDB 的写操作事务

    什么是 writeConcern?

    writeConcern 决定一个写操作落到多少个节点上才算成功(决定了 MongoDB 是否会丢失数据)。

    writeConcern 的取值有以下几种。

    • w: 0

    发起写操作,不关心是否成功。

    • w: 1 ~ 集群的最大数据节点数

    写操作需要被复制到指定的节点数,才算成功。

    • w: “majority”

    写操作需要被复制到大多数节点上,才算成功(推荐使用)。

    • w: “all”

    全部节点都需要确认写入,才算成功。

    发起写操作的程序,将阻塞到写操作到达指定的节点数为止。

    MongoDB 的数据丢失

    在这里插入图片描述

    当应用程序尝试写入一条数据"x = 1",首先进入 primary 节点,如果没有做任何设置,writePreference 默认只写一个节点,一旦写入 primary 则马上返回,表示成功(甚至可能没有写入磁盘,只是保存在 primary 的内存中)。

    图中指向从节点的虚线,表示将主节点的写入数据同步复制到从节点上,这个同步的过程是由后台的线程进行的。

    所谓的数据丢失,就是指在同步复制的过程中,主节点写入后立马返回,但马上就 crash 宕机,导致从节点并没有复制成功。此时从节点进行新的主节点选举,来继续服务于客户端,但从节点上并没有刚才写入的数据(实际上数据并未丢失,MongDB 会把数据写入到备用文件 —— rollback 文件中)。

    writeConcern 的 journal 属性

    writeConcern 可以决定写操作到达多少个节点才算成功,而 journal 则是决定如何才算成功,保证数据库节点在宕机后可以快速恢复刚才的写操作。

    • j: true

    写操作落到 journal 文件中才算成功。

    • j: false

    写操作到达内存中才算成功。

    在这里插入图片描述

    writeConcern 的注意事项

    • 虽然多于半数的 writeConcern 都是安全的,但通常只设置为 majority,因为这是等待写入延迟时间最短的选择
    • 不要设置 writeConcern 等于总节点数,因为一旦出现某个节点故障,那么所有的写操作都将失败
    • writeConcern 虽然会增加写操作的延迟时间,但并不会显著增加集群的压力,因此无论是否等待,写操作最终都会复制到所有节点上,设置 writeConcern 只是为了让写操作等待复制后再返回而已
    • 对重要的数据,可以使用 { w: “majority” };而对普通的数据,可以使用 { w: 1 } 以确保最佳的性能

    MongoDB 的分片集群

    MongoDB 有几种常见的部署架构。

    • 单机版

    本地开发时使用。

    • 复制集

    一主二从,高可用。

    • 分片集群

    节点数量和角色较多,横向扩展。

    为什么使用分片集群?

    • 数据容量日益增大,访问性能日渐降低
    • 支撑更多的并发用户
    • 单库数据大,不易维护
    • 地理分布数据,满足各地用户

    完整的分片集群

    在这里插入图片描述

    • 路由节点 mongos

    提供集群的单一入口,转发应用端请求;选择合适的数据节点进行读写;合并多个数据节点的返回;建议至少有 2 个。

    • 配置节点 mongod

    标准的普通实例,有 3 个节点;提供集群元数据的存储分片数据分布的映射关系。

    在这里插入图片描述

    • 数据节点 mongod

    以复制集为单位(一个分片即为一个复制集)进行横向扩展,最大为 1024 分片,且分片之间的数据不重复,所有的分片在一起才能完整工作。

    在这里插入图片描述

    MongoDB 分片集群的特点

    • 应用全透明,无特殊处理
    • 数据自动均衡
    • 动态扩容,无须下线
    • 提供三种分片方式
      • 基于范围
      • 基于 Hash
      • 基于 zone/tag

    MongoDB 分片集群的分布方式

    • 基于范围

    在这里插入图片描述

    选择一个或几个组合字段,将字段值的范围划分成范围空间(例如 chunk1、chunk2…),每个 chunk 仅作为一个逻辑区块,多个 chunk 组合起来存储到映射表中。

    • 基于 Hash

    在这里插入图片描述

    对字段做哈希,将数据随机写入到各个区块范围内,实现随机分布到各个节点上,对大量写入很友好,但对查询不友好。

    • 自定义 zone/tag

    在这里插入图片描述

    针对地域性字段进行标签化区分。

  • 相关阅读:
    鸿蒙Harmony应用开发—ArkTS声明式开发(自定义事件分发)
    SpringBoot框架实现简单定时任务
    目标检测算法——自动驾驶开源数据集汇总2(附下载链接)
    JS中script标签defer和async属性的区别
    ARM架构Linux查收看版本
    AOP在spring中的使用(基于注解的方式)
    Elasticsearch:使用 huggingface 模型的 NLP 文本搜索
    wsl使用vscode连接,远程安装C/C++ 拓展时,报错
    Java8实战-总结48
    嵌入式实时操作系统的设计与开发(互斥量学习)
  • 原文地址:https://blog.csdn.net/qq_43665821/article/details/126687740