分类
MongoDB

MongoDB 4.2 内核解析 – Change Stream(玩转mongodb4.0从入门到实践)

MongoDB 从3.6版本开始支持了 Change Stream 能力(4.0、4.2 版本在能力上做了很多增强),用于订阅 MongoDB 内部的修改操作,change stream 可用于 MongoDB 之间的增量数据迁移、同步,也可以将 MongoDB 的增量订阅应用到其他的关联系统;比如电商场景里,MongoDB 里存储新的订单信息,业务需要根据新增的订单信息去通知库存管理系统发货。

Change Stream 与 Tailing Oplog 对比

在 change stream 功能之前,如果要获取 MongoDB 增量的修改,可以通过不断 tailing oplog 的方式来 拉取增量的 oplog ,然后针对拉取到的 oplog 集合,来过滤满足条件的 oplog。这种方式也能满足绝大部分场景的需求,但存在如下的不足。

  1. 使用门槛较高,用户需要针对 oplog 集合,打开特殊选项的的 tailable cursor ("tailable": true, "awaitData" : true)。
  2. 用户需要自己管理增量续传,当拉取应用 crash 时,用户需要记录上一条拉取oplog的 ts、h 等字段,在下一次先定位到指定 oplog 再继续拉取。
  3. 结果过滤必须在拉取侧完成,但只需要订阅部分 oplog 时,比如针对某个 DB、某个 Collection、或某种类型的操作,必须要把左右的 oplog 拉取到再进行过滤。
  4. 对于 update 操作,oplog 只包含操作的部分内容,比如 {$set: {x: 1}} ,而应用经常需要获取到完整的文档内容。
  5. 不支持 Sharded Cluster 的订阅,用户必须针对每个 shard 进行 tailing oplog,并且这个过程中不能有 moveChunk 操作,否则结果可能乱序。

MongoDB Change Stream 解决了 Tailing oplog 存在的不足

  1. 简单易用,提供统一的 Change Stream API,一次 API 调用,即可从 MongoDB Server 侧获取增量修改。
  2. 统一的进度管理,通过 resume token 来标识拉取位置,只需在 API 调用时,带上上次结果的 resume token,即可从上次的位置接着订阅。
  3. 支持对结果在 Server 端进行 pipeline 过滤,减少网络传输,支持针对 DB、Collection、OperationType 等维度进行结果过滤。
  4. 支持 fullDocument: "updateLookup" 选项,对于 update,返回当时对应文档的完整内容。
  5. 支持 Sharded Cluster 的修改订阅,相同的 API 请求发到 mongos ,即可获取集群维度全局有序的修改。

Change Stream 实战

以 Mongo shell 为例,使用 Change Stream 非常简单,mongo shell 封装了针对整个实例、DB、Collection 级别的订阅操作。

db.getMongo().watch()    订阅整个实例的修改
db.watch()               订阅指定DB的修改
db.collection.watch()    订阅指定Collection的修改
  • 新建连接1发起订阅操作
mytest:PRIMARY>db.coll.watch([], {maxAwaitTimeMS: 60000})  最多阻塞等待 1分钟
  • 新建连接2写入新数据
mytest:PRIMARY> db.coll.insert({x: 100})
WriteResult({ "nInserted" : 1 })
mytest:PRIMARY> db.coll.insert({x: 101})
WriteResult({ "nInserted" : 1 })
mytest:PRIMARY> db.coll.insert({x: 102})
WriteResult({ "nInserted" : 1 })
  • 连接1上收到 Change Stream 更新
mytest:PRIMARY> db.watch([], {maxAwaitTimeMS: 60000})
{ "_id" : { "_data" : "825E0D5E35000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E353BE5C36D695042C90004" }, "operationType" : "insert", "clusterTime" : Timestamp(1577934389, 1), "fullDocument" : { "_id" : ObjectId("5e0d5e353be5c36d695042c9"), "x" : 100 }, "ns" : { "db" : "test", "coll" : "coll" }, "documentKey" : { "_id" : ObjectId("5e0d5e353be5c36d695042c9") } }
{ "_id" : { "_data" : "825E0D5E37000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E373BE5C36D695042CA0004" }, "operationType" : "insert", "clusterTime" : Timestamp(1577934391, 1), "fullDocument" : { "_id" : ObjectId("5e0d5e373be5c36d695042ca"), "x" : 101 }, "ns" : { "db" : "test", "coll" : "coll" }, "documentKey" : { "_id" : ObjectId("5e0d5e373be5c36d695042ca") } }
{ "_id" : { "_data" : "825E0D5E39000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E393BE5C36D695042CB0004" }, "operationType" : "insert", "clusterTime" : Timestamp(1577934393, 1), "fullDocument" : { "_id" : ObjectId("5e0d5e393be5c36d695042cb"), "x" : 102 }, "ns" : { "db" : "test", "coll" : "coll" }, "documentKey" : { "_id" : ObjectId("5e0d5e393be5c36d695042cb") } }
  • 上述 ChangeStream 结果里,_id 字段的内容即为 resume token,标识着 oplog 的某个位置,如果想从某个位置继续订阅,在 watch 时,通过 resumeAfter 指定即可。比如每个应用订阅了上述3条修改,但只有第一条已经成功消费了,下次订阅时指定第一条的 resume token 即可再次订阅到接下来的2条。
mytest:PRIMARY> db.coll.watch([], {maxAwaitTimeMS: 60000, resumeAfter: { "_data" : "825E0D5E35000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E353BE5C36D695042C90004" }})
{ "_id" : { "_data" : "825E0D5E37000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E373BE5C36D695042CA0004" }, "operationType" : "insert", "clusterTime" : Timestamp(1577934391, 1), "fullDocument" : { "_id" : ObjectId("5e0d5e373be5c36d695042ca"), "x" : 101 }, "ns" : { "db" : "test", "coll" : "coll" }, "documentKey" : { "_id" : ObjectId("5e0d5e373be5c36d695042ca") } }
{ "_id" : { "_data" : "825E0D5E39000000012B022C0100296E5A1004EA4E00977BCC482FB44DEED9A3C2999946645F696400645E0D5E393BE5C36D695042CB0004" }, "operationType" : "insert", "clusterTime" : Timestamp(1577934393, 1), "fullDocument" : { "_id" : ObjectId("5e0d5e393be5c36d695042cb"), "x" : 102 }, "ns" : { "db" : "test", "coll" : "coll" }, "documentKey" : { "_id" : ObjectId("5e0d5e393be5c36d695042cb") } }

Change Stream 内部实现

watch() wrapper

db.watch() 实际上是一个 API wrapper,实际上 Change Stream 在 MongoDB 内部实际上是一个 aggregation 命令,只是加了一个特殊的 $changestream 阶段,在发起 change stream 订阅操作后,可通过 db.currentOp() 看到对应的 aggregation/getMore 操作的详细参数。

{
      "op" : "getmore",
      "ns" : "test.coll",
      "command" : {
        "getMore" : NumberLong("233479991942333714"),
        "collection" : "coll",
        "maxTimeMS" : 50000,
        "lsid" : {
          "id" : UUID("e4fffa71-e168-4527-be61-f0918849d107")
        },
      },
      "planSummary" : "COLLSCAN",
      "cursor" : {
        "cursorId" : NumberLong("233479991942333714"),
        "createdDate" : ISODate("2019-12-31T06:35:52.479Z"),
        "lastAccessDate" : ISODate("2019-12-31T06:36:09.988Z"),
        "nDocsReturned" : NumberLong(1),
        "nBatchesReturned" : NumberLong(1),
        "noCursorTimeout" : false,
        "tailable" : true,
        "awaitData" : true,
        "originatingCommand" : {
          "aggregate" : "coll",
          "pipeline" : [
            {
              "$changeStream" : {
                "fullDocument" : "default"
              }
            }
          ],
          "cursor" : {

          },
          "lsid" : {
            "id" : UUID("e4fffa71-e168-4527-be61-f0918849d107")
          },
          "$clusterTime" : {
            "clusterTime" : Timestamp(1577774144, 1),
            "signature" : {
              "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
              "keyId" : NumberLong(0)
            }
          },
          "$db" : "test"
        },
        "operationUsingCursorId" : NumberLong(7019500)
      },
      "numYields" : 2,
      "locks" : {

      }
    }

resume token

resume token 用来描述一个订阅点,本质上是 oplog 信息的一个封装,包含 clusterTime、uuid、documentKey等信息,当订阅 API 带上 resume token 时,MongoDB Server 会将 token 转换为对应的信息,并定位到 oplog 起点继续订阅操作。

struct ResumeTokenData {
    Timestamp clusterTime;
    int version = 0;
    size_t applyOpsIndex = 0;
    Value documentKey;
    boost::optional<UUID> uuid;
};

ResumeTokenData 结构里包含 version 信息,在 4.0.7 以前的版本,version 均为0; 4.0.7 引入了一种新的 resume token 格式,version 为 1; 另外在 3.6 版本里,Resume Token 的编码与 4.0 也有所不同;所以在版本升级后,有可能出现不同版本 token 无法识别的问题,所以尽量要让 MongoDB Server 所有组件(Replica Set 各个成员,ConfigServer、Mongos)都保持相同的内核版本。

updateLookup

Change Stream 支持针对 update 操作,获取当前的文档完整内容,而不是仅更新操作本身,比如

mytest:PRIMARY> db.coll.find({_id: 101})
{ "_id" : 101, "name" : "jack", "age" : 18 }
mytest:PRIMARY> db.coll.update({_id: 101}, {$set: {age: 20}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

上面的 update 操作,默认情况下,change stream 会收到 {_id: 101}, {$set: {age: 20} 的内容,而并不会包含这个文档其他未更新字段的信息;而加上 fullDocument: "updateLookup" 选项后,Change Stream 会根据文档 _id 去查找文档当前的内容并返回。

需要注意的是,updateLookup 选项只能保证最终一致性,比如针对上述文档,如果连续更新100次,update 的 change stream 并不会按顺序收到中间每一次的更新,因为每次都是去查找文档当前的内容,而当前的内容可能已经被后续的修改覆盖。

Sharded cluster

Change Stream 支持针对 sharded cluster 进行订阅,会保证全局有序的返回结果;为了达到全局有序这个目标,mongos 需要从每个 shard 都返回订阅结果按时间戳进行排序合并返回。

在极端情况下,如果某些 shard 写入量很少或者没有写入,change stream 的返回延时会受到影响,因为需要等到所有 shard 都返回订阅结果;默认情况下,mongod server 每10s会产生一条 Noop 的特殊oplog,这个机制会间接驱动 sharded cluster 在写入量不高的情况下也能持续运转下去。

由于需要全局排序,在 sharded cluster 写入量很高时,Change Stream 的性能很可能跟不上;如果对性能要求非常高,可以考虑关闭 Balancer,在每个 shard 上各自建立 Change Stream。

作者:张友东

本文为阿里云原创内容,未经允许不得转载。

分类
MongoDB

赋予企业级开源无限可能,阿里云首发云数据库MongoDB 4.2版本

阿里云MongoDB 4.2版提供分布式事务、通配符索引、字段级加密等一系列重磅新功能,让云上用户可以第一时间体验最新版本,构建更高效、更灵活的应用。

作为全球领先的通用数据库平台,MongoDB是世界排名第一的NoSQL数据库,同时也是业界最受欢迎的开源数据库之一,曾连续四年被评为最受开发人员青睐的数据库,一举一动都影响着成千上万的企业。

阿里云与MongoDB的合作,重新打通了企业在云上使用MongoDB开源版本的通道,阿里云MongoDB云数据库是MongoDB企业用户上云的不二之选。

阿里云是国内最早提供MongoDB服务的云厂商,于 2016年即正式商用,提供完全兼容MongoDB协议的云托管数据库服务。经过多年历练,阿里云已成为中国最大的MongoDB云服务集群之一,目前广泛应用于游戏、物联网、金融、物流等行业。

基于MongoDB社区版开源内核,阿里云MongoDB结合ApsaraDB数据库管控技术栈,在内核、服务等层面进行了多项优化。随着MongoDB 4.2全新版本的发布,阿里云还将为用户提供端到端的管理和支持,让云上用户获得更优质的云数据库服务体验。

从NoSQL到NewSQL,全面升级

  • MongoDB 4.2版本新特性

分布式事务(Destributed Transaction)

采用二段提交方式,保证分片集群事务的 ACID 特性。极大地拓展了 MongoDB 的业务场景,实现从 NoSQL 到 NewSQL 的飞跃。

可重试读(Retryable Read)

增加可重试读功能,提供弱网环境下自动重试能力,降低业务端逻辑复杂性,保证用户业务连续性。

通配符索引(Wildcard Index)

对于非确定字段,MongoDB支持创建通配符索引,覆盖一个文档下的多个特征字段,所以管理更方便,使用更灵活。

字段级加密(Field Level Encryption)

驱动层面支持字段级加密,可以针对特定敏感信息,比如账号,密码,价格,手机号等信息单独加密,避免全库加密,提升业务灵活性和安全性。

物化视图(On-Demand Materialized View )

通过最新的物化视图可以缓存计算结果,避免每次重复计算,提升运行效率,减少逻辑复杂度。

赋予企业级开源无限可能

  • MongoDB云数据库8大优势

除了平台提供的增值能力,阿里云MongoDB云数据库基于社区版开源内核,结合ApsaraDB数据库管控技术栈,在MongoDB内核、服务及相关生态方面进行了众多优化,皆在为云上用户提供更优质的云数据库服务。

企业级内核能力

  • 高可用,默认3节点副本集,集合管控平台的 HA 系统,提供自动故障切换能力,保障业务持续高可用,数据高可靠。
  • 安全加固,提供全链路的安全保障,SSL 保障传输数据加密,TDE 保障存储数据加密。并通过白名单、鉴权等机制保障数据库免受黑客入侵。
  • 审计日志,支持不同粒度的审计能力,用户可以配置对关心的请求记录详细的审计日志,做到访问记录都有据可查。
  • 持续备份,MongoDB云数据库会每日做全量备份,并持续拉取oplog做增量备份,提供任意时间点备份恢复的能力,保障数据万无一失。

企业级服务能力

  • 开箱即用,用户只需在控制台上一键购买,就可以体验 MongoDB 数据库,无需担忧数据库部署、运维问题。
  • 弹性伸缩,MongoDB 云数据库能根据业务的需求灵活的升级/降级配置,结合 MongoDB 本身副本集、分片集群的优势,同时支持垂直升降级、水平升降级(增减复制集节点、增减集群分片)。
  • 秒级监控,提供秒级别的性能数据监控,所有的运行状态一目了然。
  • 自动化运维平台,自动分析运行慢日志,智能索引推荐,帮助用户更好的使用 MongoDB。

过去几年,云数据库的采用率不断上升。据Gartner 预测,到2023年全球3/4的数据库都会跑在云上。阿里云现位居全球云数据库市场份额第三,年增速115%。

阿里云拥有国内最丰富的云数据库产品,目前已有超过40万个数据库迁移到阿里云上,涵盖金融、电信、制造、物流等领域的龙头企业。

在今年国际权威机构Forrester发布的数据库评估报告《The ForresterWave?:Database-As-A-Service,Q2 2019》中,阿里云数据库跻身“强劲表现者”阵营。2018年,阿里云成为首家且唯一一家进入Gartner数据库魔力象限——远见者象限的中国公司。

作者:Roin123

本文为云栖社区原创内容,未经允许不得转载。

分类
MongoDB

基于 MongoDB 及 Spring Boot 的文件服务器的实现

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

本文将介绍通过 MongoDB 存储二进制文件,从而实现一个文件服务器 MongoDB File Server。

文件服务器的需求

本文件服务器致力于小型文件的存储,比如博客中图片、普通文档等。由于MongoDB 支持多种数据格式的存储,对于二进制的存储自然也是不话下,所以可以很方便的用于存储文件。由于 MongoDB 的 BSON 文档对于数据量大小的限制(每个文档不超过16M),所以本文件服务器主要针对的是小型文件的存储。对于大型文件的存储(比如超过16M),MongoDB 官方已经提供了成熟的产品 GridFS,读者朋友可以自行了解。

本文不会对 MongoDB 的概念、基本用法做过多的介绍,有兴趣的朋友可自行查阅其他文献,比如,笔者所著的《分布式系统常用技术及案例分析》一书,对 MongoDB 方面也有所着墨。

所需环境

本例子采用的开发环境如下:

  • MongoDB 3.4.4

  • Spring Boot 1.5.3.RELEASE

  • Thymeleaf 3.0.3.RELEASE

  • Thymeleaf Layout Dialect 2.2.0

  • Embedded MongoDB 2.0.0

  • Gradle 3.5

其中,Spring Boot 用于快速构建一个可独立运行的 Java 项目;Thymeleaf 作为前端页面模板,方便展示数据;Embedded MongoDB 则是一款由 Organization Flapdoodle OSS 出品的内嵌 MongoDB,可以在不启动 MongoDB 服务器的前提下,方面进行相关的 MongoDB 接口测试;Gradle 是一个类似于 Apache Maven 概念的新一代项目自动化构建工具。

有关 Spring Boot 的方面的内容,可以参阅笔者所著著的开源书《Spring Boot 教程》。有关 Thymeleaf 的方面的内容,可以参阅笔者所著著的开源书《Thymeleaf 教程》。有关 Gradle 的方面的内容,可以参阅笔者所著著的开源书《Gradle 3 用户指南》。

build.gradle

本文所演示的项目,是采用 Gradle 进行组织以及构建的,如果您对 Gradle 不熟悉,也可以自行将项目转为 Maven 项目。

build.gradle 文件内容如下:

// buildscript 代码块中脚本优先执行buildscript { // ext 用于定义动态属性

该 build.gradle 文件中的各配置项的注释已经非常详尽了,这里就不再赘述其配置项的含义了。

领域对象

文档类 File

文档类是类似与 JPA 中的实体的概念。

import org.springframework.data.mongodb.core.mapping.Document;

文档类,主要采用的是 Spring Data MongoDB 中的注解,用于标识这是个 NoSQL 中的文档概念。

存储库 FileRepository

存储库用于提供与数据库打交道的常用的数据访问接口。其中 FileRepository 接口继承自org.springframework.data.mongodb.repository.MongoRepository即可,无需自行实现该接口的功能,

Spring Data MongoDB 会自动实现接口中的方法。

import org.springframework.data.mongodb.repository.MongoRepository;import com.waylau.spring.boot.fileserver.domain.File;public interface FileRepository extends MongoRepository<File, String> {

服务接口及实现类

FileService 接口定义了对于文件的 CURD 操作,其中查询文件接口是采用的分页处理,以有效提高查询性能。

public interface FileService { /**

FileServiceImpl 实现了 FileService 中所有的接口。

@Servicepublic class FileServiceImpl implements FileService {

控制层/API 资源层

FileController 控制器作为 API 的提供者,接收用户的请求及响应。API 的定义符合 RESTful 的风格。有关 REST 相关的知识,读者可以参阅笔者所著的开源书《[REST 实战]》(https://github.com/waylau/rest-in-action)。

@CrossOrigin(origins = "*", maxAge = 3600) // 允许所有域名访问@Controllerpublic class FileController { @Autowired

其中@CrossOrigin(origins = "*", maxAge = 3600) 注解标识了 API 可以被跨域请求。为了能够启用该注解,仍然需要安全配置类的支持。

安全配置

为了支持跨域请求,我们设置了安全配置类 SecurityConfig:

@[email protected] class SecurityConfig extends WebMvcConfigurerAdapter { @Override

运行

有多种方式可以运行 Gradle 的 Java 项目。使用 Spring Boot Gradle Plugin 插件运行是较为简便的一种方式,只需要执行:

$ gradlew bootRun

其他运行方式,请参阅笔者的开源书《Spring Boot 教程》

项目成功运行后,通过浏览器访问 http://localhost:8081 即可。首页提供了上传的演示界面,上传后,就能看到上传文件的详细信息:

相关上传的接口暴露在了 http://localhost:8081/ ,其中

  • GET /files/{pageIndex}/{pageSize} : 分页查询已经上传了的文件

  • GET /files/{id} : 下载某个文件

  • GET /view/{id} : 在线预览某个文件。比如,显示图片

  • POST /upload : 上传文件

  • DELETE /{id} : 删除文件

源码

MongoDB File Server 是一款开源的产品,完整的项目源码见 https://github.com/waylau/mongodb-file-server。

参考文献

  • 原文同步至:https://waylau.com/mogodb-file-server-with-spring-boot/

  • 《https://docs.mongodb.com/manual/core/gridfs/

  • 《分布式系统常用技术及案例分析》:https://github.com/waylau/distributed-systems-technologies-and-cases-analysis

  • 《Spring Boot 教程》:https://github.com/waylau/spring-boot-tutorial

  • 《Thymeleaf 教程》:https://github.com/waylau/thymeleaf-tutorial

  • 《Gradle 3 用户指南》:https://github.com/waylau/gradle-3-user-guide

  • 《REST 实战》https://github.com/waylau/rest-in-action

  • https://github.com/waylau/mongodb-file-server

分类
MongoDB

MongoDB报告:复杂架构阻碍企业创新;数据是最大痛点

中国企业认为创新至关重要,但因复杂的数据基础架构而受到阻碍

36% 的受访者表示云计算让复杂性进一步加剧

2022年 5 月 10 日——中国企业普遍认为技术创新对于推动未来增长至关重要,但61%的企业表示复杂的数据基础架构阻碍了这一进程。

全球领先的现代通用数据库平台MongoDB近期发布《2022 MongoDB数据与创新报告》,该调查报告是一项针对亚太地区2,000余名(包括中国400余名)开发者、IT决策者等专业技术人士的详尽调研,展示了创新的重要性,以及阻碍创新的隐性负担。

创新是当务之急,但时间却没有被用在刀刃上

在中国,81%的受访者表示,数据处理是应用程序构建过程中最困难的环节,而在应用程序开发过程中面临的最大技术挑战则是处理不同格式的海量数据。

尽管高达92%的受访者认为定期构建新的应用程序和功能是企业获得长期成功的关键,但许多机构认为能真正用于创新的时间非常有限。受访的开发团队和IT决策者均表示,他们在现有数据、应用程序和基础设施维护方面所花费的时间(27%)与用于构建全新的增值功能或应用程序的时间(28%)基本相当。

调查指出,47%的受访者认为其组织机构的数据架构较为复杂,61%的受访者认为这种复杂性是制约创新的主要因素。受访企业表示,无法创新所导致的最严重后果将是成本上升,及无法从数据洞察获得竞争优势。

MongoDB公司首席技术官Mark Porter表示:“纵观所有处于创新前沿的公司,我们会发现,这些公司并没有将创新外包给第三方。相反,这些组织机构的管理层深谙软件构建的复杂性,所以更加愿意为自己的开发团队配备有效的解决方案,帮助他们提高效率。而我们的调查结果与从企业高管处获悉的信息是一致的。企业正因为使用复杂的遗留技术而让开发团队的工作受到影响。负责数字化转型项目的企业高管应该聚焦于如何尽快部署应用程序、更快地迭代,以及有效安排发布排期。”

对于多数企业而言,上云和数字化转型增加了复杂性

大多数机构(58%)认为数字化转型使其数据架构变得更加复杂。然而,在谈到上云时,一些公司显然有着不同的体验。45%的受访者表示,迁移到云端有助于简化其数据架构,而36%的受访者则表示,上云实际使其数据架构变得更加复杂。遗留数据基础设施被视为另一个创新制约因素,59%的受访者表示其阻碍了创新技术的发展。

随着对现代应用需求的日益增长,诸如搜索功能或移动应用程序等更多内容被陆续添加,这会导致整体构架随之臃肿。例如,31%的企业称其数据库数量多达10个以上。这意味着,开发人员需要花时间维护不同的多个数据模型、集成数据源、支持遗留系统及安全修复等方面。

MongoDB北亚区副总裁苏玉龙表示:“从调查中可以清楚地看出,并非所有企业都能享受到云带来的各种益处。许多机构只是将现有的基础架构迁移至云平台,再一步一步添加新服务,致使本地存在的问题在云平台上还是一样会存在。企业应该采取不同的方法。我们注意到,一些最具创新性的企业对应用平台进行战略性投资,从根本上改善四大关键领域,1)提高开发人员效率,2)优先考虑使用优质且可重复使用的架构,3)轻松实现数据安全与隐私保护,以及4)采用既具有部署灵活性又侧重于多云模式的方法。”

该调查结果还包括:

? 创新的首要任务是提高内部效率/生产力

? 造成数据复杂性的最大因素是开发新产品或新功能的压力

? 最大的技术挑战是处理不同格式的海量数据

如需获得报告全文,请点击下载: 2022 MongoDB 数据与创新报告

关于MongoDB

MongoDB是全球领先的现代通用数据库平台,旨在助力开发人员及其构建的应用程序释放软件和数据的力量来创造、转变和颠覆行业。MongoDB总部位于纽约,在全球100多个国家和地区拥有33,000多家客户。MongoDB数据库平台下载量已超过2.1亿次,MongoDB University全球注册用户累计已超过150万。

数据说明

*MongoDB携手CensusWide公司,对印度、中国香港、中国台湾、澳大利亚、新西兰、中国内地和韩国等国家和地区的2,043名受访者进行了调研。我们的调研对象为开发人员和IT决策者。

开发人员指“从事软件应用程序构建和创建的人员,其职责包括编写、调试和执行应用程序代码。”

IT决策者指“获授权在公司内制定战略性IT决策的员工,包括(但不限于):IT专业人员的招聘、全新IT软件和硬件的采购、以技术为重点的研发决策、数据管理和数据安全等。”

分类
MongoDB

MongoDB CPU 利用率高,怎么破?(mongo cpu占用高)

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud

经常有用户咨询「MongoDB CPU 利用率很高,都快跑满了」,应该怎么办?

遇到这个问题,99.9999% 的可能性是「用户使用上不合理导致」,本文主要介绍从应用的角度如何排查 MongoDB CPU 利用率高的问题

Step1: 分析数据库正在执行的请求

用户可以通过 Mongo Shell 连接,并执行 db.currentOp() 命令,能看到数据库当前正在执行的操作,如下是该命令的一个输出示例,标识一个正在执行的操作。重点关注几个字段

  • client:请求是由哪个客户端发起的?

  • opid:操作的opid,有需要的话,可以通过 db.killOp(opid) 直接干掉的操作

  • secs_running/microsecs_running: 这个值重点关注,代表请求运行的时间,如果这个值特别大,就得注意了,看看请求是否合理

  • query/ns: 这个能看出是对哪个集合正在执行什么操作

  • lock*:还有一些跟锁相关的参数,需要了解可以看官网文档,本文不做详细介绍

db.currentOp 文档在这里,多看官网文档

 { "desc" : "conn632530", "threadId" : "140298196924160", "connectionId" : 632530, "client" : "11.192.159.236:57052", "active" : true, "opid" : 1008837885, "secs_running" : 0, "microsecs_running" : NumberLong(70), "op" : "update", "ns" : "mygame.players", "query" : { "uid" : NumberLong(31577677)

这里先要明确一下,通过 db.currentOp() 查看正在执行的操作,目的到底是什么?

并不是说我们要将正在执行的操作都列出来,然后通过 killOp 逐个干掉;这一步的目的是要看一下,是否有「意料之外」的耗时请求正在执行。

比如你的业务平时 CPU 利用率不高,运维管理人员连到数据库执行了一些需要全表扫描的操作,然后突然 CPU 利用率飙高,导致你的业务响应很慢,那么就要重点关注下那些执行时间很长的操作。

一旦找到罪魁祸首,拿到对应请求的 opid,执行 db.killOp(opid) 将对应的请求干掉。

如果你的应用一上线,cpu利用率就很高,而且一直持续,通过 db.currentOp 的结果也没发现什么异常请求,可以进入到 Step2 进行更深入的分析。

Step2:分析数据库慢请求

MongoDB 支持 profiling 功能,将请求的执行情况记录到同DB下的 system.profile 集合里,profiling 有3种模式

profiling 设置文档在这里,多看官网文档

  • 关闭 profiling

  • 针对所有请求开启 profiling,将所有请求的执行都记录到 system.profile 集合

  • 针对慢请求 profiling,将超过一定阈值的请求,记录到system.profile 集合

默认请求下,MongoDB 的 profiling 功能是关闭,生产环境建议开启,慢请求阈值可根据需要定制,如不确定,直接使用默认值100ms。

operationProfiling: mode: slowOp

基于上述配置,MongoDB 会将超过 100ms 的请求记录到对应DB 的 system.profile 集合里,system.profile 默认是一个最多占用 1MB 空间的 capped collection。

查看最近3条 慢请求,{$natrual: -1} 代表按插入数序逆序

在开启了慢请求 profiling 的情况下(MongoDB 云数据库是默认开启慢请求 profiling的),我们对慢请求的内容进行分析,来找出可优化的点,常见的包括。

profiling的结果输出含义在这里,多看官网文档

CPU杀手1:全表扫描

全集合(表)扫描 COLLSCAN,当一个查询(或更新、删除)请求需要全表扫描时,是非常耗CPU资源的,所以当你在 system.profile 集合 或者 日志文件发现 COLLSCAN 关键字时,就得注意了,很可能就是这些查询吃掉了你的 CPU 资源;确认一下,如果这种请求比较频繁,最好是针对查询的字段建立索引来优化。

一个查询扫描了多少文档,可查看 system.profile 里的 docsExamined 的值,该值越大,请求CPU开销越大。

关键字:COLLSCAN、 docsExamined

CPU杀手2:不合理的索引

有的时候,请求即使查询走了索引,执行也很慢,通常是因为合理建立不太合理(或者是匹配的结果本身就很多,这样即使走索引,请求开销也不会优化很多)。

如下所示,假设某个集合的数据,x字段的取值很少(假设只有1、2),而y字段的取值很丰富。

{ x: 1, y: 1 }

要服务 {x: 1: y: 2} 这样的查询

db.createIndex( {x: 1} ) 效果不好,因为x相同取值太多db.createIndex( {x: 1, y: 1} ) 效果不好,因为x相同取值太多db.createIndex( {y: 1 } ) 效果好,因为y相同取值很少db.createIndex( {y: 1, x: 1 } ) 效果好,因为y相同取值少

至于{y: 1} 与 {y: 1, x: 1} 的区别,可参考MongoDB索引原理 及 复合索引官方文档 自行理解。

一个走索引的查询,扫描了多少条索引,可查看 system.profile 里的 keysExamined 字段,该值越大,CPU 开销越大。

关键字:IXSCAN、keysExamined

CPU杀手3:大量数据排序

当查询请求里包含排序的时候,如果排序无法通过索引满足,MongoDB 会在内存李结果进行排序,而排序这个动作本身是非常耗 CPU 资源的,优化的方法仍然是建立索引,对经常需要排序的字段,建立索引。

当你在 system.profile 集合 或者 日志文件发现 SORT 关键字时,就可以考虑通过索引来优化排序。当请求包含排序阶段时, system.profile 里的 hasSortStage 字段会为 true。

关键字:SORT、hasSortStage

其他还有诸如建索引,aggregationv等操作也可能非常耗 CPU 资源,但本质上也是上述几种场景;建索引需要全表扫描,而vaggeregation 也是遍历、查询、更新、排序等动作的组合。

Step3: 服务能力评估

经过上述2步,你发现整个数据库的查询非常合理,所有的请求都是高效的走了索引,基本没有优化的空间了,那么很可能是你机器的服务能力已经达到上限了,应该升级配置了(或者通过 sharding 扩展)。

当然最好的情况时,提前对 MongoDB 进行测试,了解在你的场景下,对应的服务能力上限,以便及时扩容、升级,而不是到 CPU 资源用满,业务已经完全撑不住的时候才去做评估。

分类
MongoDB

MongoDB 5.0.6 发布,数据库管理系统(mongodb数据库管理工具)

MongoDB 是一种面向文档的数据库管理系统,用 C++ 等语言撰写而成,以解决应用程序开发社区中的大量现实问题。MongoDB 由 MongoDB Inc. 于 2007 年 10 月开发,2009 年 2 月首度推出,现以服务器端公共许可(SSPL)分发。

MongoDB 5.0.6 现已正式发布,本次更新内容如下:

Platform Support

Community Edition

从 MongoDB 5.0.6 开始,不再支持以下平台:

  • RHEL -72-s390x

Sharding

  • SERVER-45149 txn_two_phase_commit_failover.js 中的 replSetStepDown 命令不应超时
  • SERVER-56127 如果 chunk 被迁移并且 shard key pattern 使用嵌套字段,Retryable update 可能会执行多次
  • SERVER-56227 添加面向用户的命令,为 sharded collection 设置 allowMigrations 为 false。
  • SERVER-60624 txn_commit_optimizations_for_read_only_shards.js 暂停协调器上的复制,并且可能使 transaction 卡在准备阶段
  • SERVER-60682 TransactionCoordinator 可能会阻止获取 WiredTiger 写票以坚持其决定,从而延长 transactions 处于准备状态
  • SERVER-60860 在最接近的情况下,ReshardingCollectionCloner 使用 primary 读取 preference
  • SERVER-61003 来自 ShardRegistry 的 ReadConcernMajorityNotAvailableYet errors 必须重试
  • SERVER-61105 moveChunk 期间的会话迁移逻辑污染日志
  • ……

Replication

  • SERVER-59721 执行回滚到稳定时间戳后,节点可能无法与其他 members 同步

Query

  • SERVER-57588 当数组位置被索引其值为数组时,查询结果不一致

Storage

  • SERVER-30846 在 FSM 测试中将 dbCheck 作为后台工作负载运行
  • SERVER-55483 添加一个新的启动参数,跳过验证表日志设置
  • SERVER-58409 Startup RecordId 初始化存在持久历史和重建准备事务的缺陷

Operations

  • SERVER-28953 在 FTDC 中捕获 df(disk full)统计信息

Internals

  • SERVER-49748 初始同步应在任何其他集合之前克隆 admin.system.version
  • SERVER-54468 启用最小化支持 sharding time-series collections 的特性标志
  • SERVER-56167 保证挂起分析器至少收集 sharded clusters 的核心转储
  • SERVER-57037 提高 operator counters 的精度
  • SERVER-57289 redact 不应将 BSONArray 转换为 BSONObj
  • SERVER-58135 ReplSetTest 在禁用链接的 replica sets 中启动失败
  • SERVER-59781 multi_statement_transaction.js 不在 StaleConfig 上重试 transaction
  • SERVER-60217 [v5.0] enableReconfigRollbackCommittedWritesCheck 应应用于 4.4
  • SERVER-60310 OCSP 响应验证不应考虑不相关证书的状态
  • ……

更多详情可查看:https://docs.mongodb.com/v5.0/release-notes/5.0-changelog#5.0.6-changelog

分类
MongoDB

千万别用MongoDB?真的吗?!(使用mongodb的好处)

某人发了一篇Don’t use MongoDB的血泪控诉,我把原文翻译如下,你可以看看。不过,我想我们还要去看看10gen CTO的对此事的回复,我们还要去在Reddit上看看大家的说法,10gen CTO的对此事的回复后面也有一堆人在讨论这个事,还有一些程序员开始去读MongoDB的源码了,呵呵。看样子,说MongoDB的这些事并不是真的。

10gen CTO 对此事的并不完全知道,其在回复,对些文中的每一条都做了回复。我把其回复的大体意思也放在原文中。不过,很有意思的是那些程序员的讨论。建议大家看看。

正文

因为各种政治原因,我这段时间没有说什么,但是现在我觉得因为要对社会负责,所以我要阻止大家不要把你们的业务放在MongoDB上。

我的团队在一个有巨大用户量(一个有千万用户级的大型的公司)系统上使用的MongoDB,这个系统上让MongoDB有非常大的负载。早期,我们以为使用MongoDB会像10gen公司(MongoDB背后的公司)宣扬其在长期性能扩展有很多好处。但是,我们错了,而这个rant(长篇抱怨)就是为了让你不要相信那些所谓的成功经验而和我们一样犯了大错。如果有人能避免你上当,那么就得我写这么多。希望能警醒更多的人。

注意,对于和10gen打交道的经历来说,他们给予了我们充分了热情和帮助,而且非常地好。但是这并不能成为我不告诉大家他们的产品失败的理由。

为什么这么说?

数据库应该是正确的,或是仅可能的正确,因为数据库的错误会比其它使用更大。不仅仅是因为其对运行,性能,开销,和其价值影响巨大,还因为其连带的东西。匆忙去去移植TB级的数据相比起去修改代码中的一个逻辑错误来说是一个很巨大的工作。而在系统出问题后需要恢复TB级的数据,而你即被限制住了,你会有一种绝望的感觉。

数据库是一个很复杂的系统,对于开发者来说就像一个黑盒一样。你需要对你所采用的数据库持绝对信任的态度,信任它会做正确的事,并尽会保持 一致笥和可用性。

为什么MongoDB会流行?

说句公道话,我们必需承认MongoDB是流行的,因为下面这些原因让其流行变得很合理:

  • 它非常容易地运行
  • 非常自由的Schema模型,而且可以很容易地和JSON类的数据结果映射起来,这对于程序员来于有很大的感染力(它完全符合程序员的逻辑思维),而且,程序员总是在项目可以做技术选型的人。
  • 成熟和分健壮,有记录,被真实的Use Case测试过,等等。对于那些喜欢选择成熟的技术的系统管理员和运营专业来说,这是一个很典型的选择。
  • 它单系统,低读并发的性能测试非常令人惊讶,而对于那些没有经验的评估者来说,这基本上来说是最重要的。

现在,你可能正在开发一个随便玩一玩的网站,或是一个原型,或是那种只考虑开发速度不考虑别的的项目。老实说,对于这种项止,无所谓你用什么样的技术,只要搞定工作就行了。

但是,如果你想要在MongoDB上搞一个大规模的系统,在上面运行真实的业务,那么,请不要用MongoDB。

为什么不?

1)MongoDB为了赢得Benchmark测试而默认使用了不安全的写方式

如果你不调用getLastError(),MongoDB就不会在确认数据库写操作完成就返回了,这会引入至少两种问题:

  • 在并发的环境下(连接池,等),在一个读操作“完成”后的连续地读操作会出错,MongoDB没有“栅栏条件锁”来知道什么时候完成写。
  • 未知个数的保存操作会被丢弃,因为保存操作的队列会在不同的地方。比如TCP缓存等。当你和数据库连接因为一些意味情况断开的时候,这些东西就被丢弃了。

10gen CTO 回复: 这和Benchmark没有任何关系,并说这个就是API的设计,其交给用户自己去选择,因为写的方式也有很多种。

2)MongoDB会以令人震惊的方式丢失数据

下面是一个我们所经历过的它丢数据的列表:

  • 数据就是丢了,原因未知
  • 从损坏的数据库中恢复数据不成功,如事务日志。
  • 主从结点间的数据复制有缺口,导致从结点丢失主结点有的数据。是的,没有CheckSum,并且是的,你还会看到数据复制过去了。
  • 数据复制有时会停了,没有错误。你可以监控你的复制状态。

10gen CTO 逐一回复:1)从来没有一个数据丢失的BUG我们没有马上fix的事情。你能告诉我你报给我们的问题号吗?我们至少要明的是怎么一回事。如果是我们的问题,我们会马上fix的。2)从损坏了的数据库中不能完全恢复数据 ,这不挺正常的吗?但是如果有主从服务器互为备份应该会好一些。3)请告诉我你的问题号,我们从来没有接到过这样的错误报告。如果有,的确很严重。4)如果是说错误条件发生的时候没有通知,这有可能。另外,你可以监控数据复制的写操作,你可以使用w=2 为getLastError的参数。

3)MongoDB 需要全局写锁来请求写操作

在写操作频繁的时候,这等同于杀了你。如果你运行一个blog,你也许不会关心这个事,因为你的读写操作不高。

10gen CTO 回复:读写锁永远都是问题,但是2.0会好很多,2.2会解决得更好一些。

4)MongoDB 的Sharding(分区) 在高负载下会停止工作

在高负载下加一个shard是一场恶梦。Mongo要么会移动其数据块太快而导致DOS攻击产生很多流量占用带宽,要么就完全地拒绝更多的数据块。这会使一个高流量的网站承受着沉重地写操作。

10gen CTO 回复:如果系统已经超过了其负载,那么移动数据当然会变得很难。我每一次的演讲都说得很清楚,不要在系统性能不行的时候才去加shard,这不行的。

5)Mongo 不可靠

Mongod/配置服务器/mongos的架构确定合理且聪明。不幸的是,mongos完全就是垃圾。在有负载的情况下,它时不时就都会崩溃,有时几个小时,有时几天。进程重启监控有时也不管用,因为他会抛出一些断言会伪造出一个关键线程,其导致进程还在运行。Double Fail。

最坏的是,唯一可行的方式是在一堆mongos实例前放一个HaProxy(一种负载均衡器),运行一个作业其缓慢地轮着访问这些mongos实例,并定期kill掉他们,以变可以重新启动新的实例。我没有在开玩笑。

10gen CTO 回复:不可能有这种事,你能不能告诉我更多的细节?

6)MongoDB有一次甚至删除了整个数据库

MongoDB 1.6,在数据同步配置中,有时会配置了一个错误的结点(经常是一个空结点)是一个最新的数据结点。于是其它同步数据的结果上的数据就这样被干掉了(我说的是700GB的好数据),因为其把这个空结点的数据同步回有数据的结点上。数据库永远永远都不应该干这个。如果出现这种问题,数据库应该抛出一个错误而让DBA来选择合理的操作,或是强制使用正确的配置。而不应该删除所有的数据(那天太糟糕了)。

他们在1.8中修复了这个问题,偶滴神啊。

10gen CTO 回复:找不到这样的事,也找不到相应提交的代码,你能多给点信息吗?

7)发布了一些不应该发布东西

众所周知,在稳定版里能找到一些尴尬的bug其会导致数据问题——而我们总是在出了问题后他们才告诉我们这些问题,这是因为我们购买了10gen他们那超级诈骗的白金技术支持。他们回应是,发给我们一个hot patch,他们内部叫RC的玩意,然后让这个hot patch运行在我们的数据上。

10gen CTO 回复:关于白金的技术支持,我们所接手的所有问题都会公开,fix也会公开。没有特定的情景,这种事很难讨论。我们会根据不同的情况作出不同的反应。我们希望我们的用户的问题能尽快得到解决。

8)复制器在繁忙的服务器上黯然失色

复制器经常性的向Master发起DOS攻击,或是复制非常慢,花了巨长无比的时间,而oplog几乎被耗尽(就算是50GB的oplog)。

我们有一个繁忙的,大的数据集我们不会复制他因为它是动态的。那是令人痛苦的一个月,或是我们需要在选择不同的数据库系统前交叉双指(注:好运的手势)

10gen CTO 回复:这看起来像上服务器负载过重了。我前面提到过了。

但是最糟糕的问题是:

你可能会说,我这些问题都是过去式了;他们修复了所有这些问题或是他们会在下一版本中修复这些问题;X问题可以用Y实践来减轻。等等,等等。

不幸的是,你说这些东西一点用也没有。

真正的问题是,这么多的问题都是首要的问题。 数据库开发者要能hold住比一般程序员更高的标准。也就是说,你的优先级应该像下面这个样子:

  1. 别搞丢数据,对数据要有完全的把握
  2. 通过实践保证可用性
  3. 多结点的性能扩展性
  4. 最小延迟应该保持在99%和95%之间
  5. 每个资源的每秒请求数

10gen的顺序好像是 #5 为每一,其它项随便,#1 并不在前3位。

10gen CTO 回复:这明显不是真的。看一看我们提交的代码,看一看我们的fix。 我们从来不会在release版中隐藏一个bug。如果我们非常在乎性能的benchmark的话,我们会花精力解决那些锁的问题,这样一来,多线程并发会更快一些。

MongoDB是一个新生的东西,还有很多东西需要打磨。如果你想来认识一下我们,我们欢迎你来认识一下我们。

这些失败,还有那所暗示的公司的优先级,指出了一个最基本的企业文化的问题,其会让问题出现在任一发布版中:因为他们缺乏尊守必要的数据库系统的设计律条。

请慎重考虑这些警告。

分类
MongoDB

MongoDB 是什么 ? 能干嘛 ?(mongodb的好处)


  • 1、MongoDB是什么?

  • 2、为什么要用MongoDB?

  • 3、主要特性

  • 4、C/S服务模型

  • 5、完善的命令行工具

  • 6、几个shell实操

  • 7、在Java中使用MongoDB


最近在回顾mongodb的相关知识,输出一篇文章做为MongoDB知识点的总结。

总结的目的在于回顾MongoDB的相关知识点,明确MongoDB在企业级应用中充当的角色,为之后的技术选型提供一个可查阅的信息简报。

1、MongoDB是什么?

MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。没错MongoDB就是数据库,是NoSQL类型的数据库

2、为什么要用MongoDB?

(1)MongoDB提出的是文档、集合的概念,使用BSON(类JSON)作为其数据模型结构,其结构是面向对象的而不是二维表,存储一个用户在MongoDB中是这样子的。

{
 username:'123',
 password:'123'
}

使用这样的数据模型,使得MongoDB能在生产环境中提供高读写的能力,吞吐量较于mysql等SQL数据库大大增强。

(2)易伸缩,自动故障转移。易伸缩指的是提供了分片能力,能对数据集进行分片,数据的存储压力分摊给多台服务器。自动故障转移是副本集的概念,MongoDB能检测主节点是否存活,当失活时能自动提升从节点为主节点,达到故障转移。

(3)数据模型因为是面向对象的,所以可以表示丰富的、有层级的数据结构,比如博客系统中能把“评论”直接怼到“文章“的文档中,而不必像myqsl一样创建三张表来描述这样的关系。

3、主要特性

(1)文档数据类型

SQL类型的数据库是正规化的,可以通过主键或者外键的约束保证数据的完整性与唯一性,所以SQL类型的数据库常用于对数据完整性较高的系统。MongoDB在这一方面是不如SQL类型的数据库,且MongoDB没有固定的Schema,正因为MongoDB少了一些这样的约束条件,可以让数据的存储数据结构更灵活,存储速度更加快。

(2)即时查询能力

MongoDB保留了关系型数据库即时查询的能力,保留了索引(底层是基于B tree)的能力。这一点汲取了关系型数据库的优点,相比于同类型的NoSQL redis 并没有上述的能力。

(3)复制能力

MongoDB自身提供了副本集能将数据分布在多台机器上实现冗余,目的是可以提供自动故障转移、扩展读能力。

(4)速度与持久性

MongoDB的驱动实现一个写入语义 fire and forget ,即通过驱动调用写入时,可以立即得到返回得到成功的结果(即使是报错),这样让写入的速度更加快,当然会有一定的不安全性,完全依赖网络。

MongoDB提供了Journaling日志的概念,实际上像mysql的bin-log日志,当需要插入的时候会先往日志里面写入记录,再完成实际的数据操作,这样如果出现停电,进程突然中断的情况,可以保障数据不会错误,可以通过修复功能读取Journaling日志进行修复。

(5)数据扩展

MongoDB使用分片技术对数据进行扩展,MongoDB能自动分片、自动转移分片里面的数据块,让每一个服务器里面存储的数据都是一样大小。

4、C/S服务模型

MongoDB核心服务器主要是通过mongod程序启动的,而且在启动时不需对MongoDB使用的内存进行配置,因为其设计哲学是内存管理最好是交给操作系统,缺少内存配置是MongoDB的设计亮点,另外,还可通过mongos路由服务器使用分片功能。

MongoDB的主要客户端是可以交互的js shell 通过mongo启动,使用js shell能使用js直接与MongoDB进行交流,像使用sql语句查询mysql数据一样使用js语法查询MongoDB的数据,另外还提供了各种语言的驱动包,方便各种语言的接入。

5、完善的命令行工具

mongodump和mongorestore,备份和恢复数据库的标准工具。输出BSON格式,迁移数据库。

mongoexport和mongoimport,用来导入导出JSON、CSV和TSV数据,数据需要支持多格式时有用。mongoimport还能用与大数据集的初始导入,但是在导入前顺便还要注意一下,为了能充分利用好mongoDB通常需要对数据模型做一些调整。

mongosniff,网络嗅探工具,用来观察发送到数据库的操作。基本就是把网络上传输的BSON转换为易于人们阅读的shell语句。

因此,可以总结得到,MongoDB结合键值存储和关系数据库的最好特性。因为简单,所以数据极快,而且相对容易伸缩还提供复杂查询机制的数据库。MongoDB需要跑在64位的服务器上面,且最好单独部署,因为是数据库,所以也需要对其进行热备、冷备处理。

6、几个shell实操

因为本篇文章不是API手册,所有这里对shell的使用也是基础的介绍什么功能可以用什么语句,主要是为了展示使用MongoDB shell的方便性,如果需要知道具体的MongoDB shell语法可以查阅官方文档。

1、切换数据库

use dba

创建数据库并不是必须的操作,数据库与集合只有在第一次插入文档时才会被创建,与对数据的动态处理方式是一致的。简化并加速开发过程,而且有利于动态分配命名空间。如果担心数据库或集合被意外创建,可以开启严格模式

2、插入语法

1db.users.insert({username:"smith"})
2db.users.save({username:"smith"})

3、查找语法

1 db.users.find()
2 db.users.count()

4、更新语法

 1 db.users.update({username:"smith"},{$set:{country:"Canada"}})
 2 //把用户名为smith的用户的国家改成Canada
 3
 4 db.users.update({username:"smith"},{$unset:{country:1}})
 5 //把用户名为smith的用户的国家字段给移除
 6
 7 db.users.update({username:"jones"},{$set:{favorites:{movies:["casablance","rocky"]}}})
 8 //这里主要体现多值修改,在favorties字段中添加多个值
 9
10 db.users.update({"favorites.movies":"casablance"},{$addToSet:{favorites.movies:"the maltese"}},false,true)
11 //多项更新

5、删除语法

1db.foo.remove() //删除所有数据
2db.foo.remove({favorties.cities:"cheyene"}) //根据条件进行删除
3db.drop() //删除整个集合

6、索引相关语法

1db.numbers.ensureIndex({num:1})
2//创建一个升序索引
3db.numbers.getIndexes()
4//获取全部索引

7、基本管理语法

 1 show dbs
 2 //查询所有数据库
 3 show collections
 4 //显示所有表
 5 db.stats()
 6 //显示数据库状态信息
 7 db.numbers.stats()
 8 //显示集合表状态信息
 9 db,shutdownServer()
10 //停止数据库
11 db.help()
12 //获取数据库操作命令
13 db.foo.help()
14 //获取表操作命令
15 tab 键 //能自动帮我们补全命令

以上的命令只是简单实例,假设如果你之前没有学习过任何数据库语法,同时开始学sql查询语法和MongoDB 查询语法,你会发现哪一个更简单呢?如果你使用的是java驱动去操作MongoDB,你会发现任何的查询都像Hibernate提供出来的查询方式一样,只要构建好一个查询条件对象,便能轻松查询(接下来会给出示例),博主之前熟悉ES6,所以入手MongoDB js shell完成没问题,也正因为这样简洁,完善的查询机制,深深的爱上了MongoDB。

7、在Java中使用MongoDB

1、使用maven引入jar包

这里引用的是最新的驱动包,提供了一套新的访问连接方式

1 <dependency>
2 <groupId>org.mongodb</groupId>
3 <artifactId>mongodb-driver-sync</artifactId>
4 <version>3.8.0-beta3</version>
5 </dependency>

2、创建一个访问客户端

1 MongoClient client = MongoClients.create(“mongodb://10.201.76.94:27017”);

3、获取集合数量

1 public long count() {
2 MongoClient client = this.getClient();
3 MongoCollection<Document> collections= client.getDatabase("mongodb_db_name").getCollection("mongodb_collection_name");
4 return collections.count();
5 }

4、查询集合

 1public List<Document> find(Document params,Bson sort,int skip,int limit) {
 2 MongoClient client = this.getClient();
 3 MongoCollection<Document> collections= client.getDatabase("mongodb_db_name").getCollection("mongodb_collection_name");
 4 List<Document> list = new ArrayList<Document>(Integer.valueOf(config.getPro("sync_limit")));
 5 collections.find(params).sort(sort).skip(skip).limit(limit).forEach(new Block<Document>() {
 6 @Override
 7 public void apply(Document document) {
 8 list.add(document);
 9 }
10 });
11 return list;
12 }

这里只举例了简单的链接与简单的MongoDB操作,可见其操作的容易性。使用驱动时是基于TCP套接字与MongoDB进行通信的,如果查询结果较多,恰好无法全部放进第一服务器中,将会向服务器发送一个getmore指令获取下一批查询结果。

插入数据到服务器时间,不会等待服务器的响应,驱动会假设写入是成功的,实际是使用客户端生成对象id,但是该行为可以通过配置配置,可以通过安全模式开启,安全模式可以校验服务器端插入的错误。

分类
MongoDB

MongoDB海量数据存储应用简述(mongodb使用数据存储)

随着应用场景增多,数据的格式也出现多样性与不确定性。常见的结构化存储如关系型数据库已经不能做到面面俱到。Nosql数据库的出现解决了很多非结构化半结构化的数据存储。MongoDB作为文档型数据库在很多领域已经被应用。

MongoDB是基于JSON来描述数据的因此具有很高的灵活性与可读性。MongoDB具备丰富的索引类型,通过建立合理的索引能够极大提高检索速度。同时MongoDB也具有强大的聚合计算能力。

鉴于MongoDB的特性在电商商品、风控等场景已被使用。

商品存储应用场景。

电商商品信息一般包含商品基本信息、商品图片信息、还会有商品的规格信息。不同商品的规格可能不同而且也不确定,这时候通过MongoDB存储规格信息是最适合不过。

风控应用场景。

风控系统能够起到保障交易安全,是防范不正常交易的屏障。常用MongoDB存储风控事件JSON,然后借助MongoDB的聚合计算能力(max、min、sum)实时产出结果快速提供风控能力。

除此之外MongoDB在企业信息认证、个人信息认证方面也有应用。

MongoDB文档型存储具有很大的扩展性这是很多应用选择使用的一大因素,另外先天的分布式设计提供了海量存储的能力。MongoDB结合关系型数据库已经被广泛应用。

分类
MongoDB

mongodb的数据如何备份

Mongodb自带了mongodump和mongorestore这两个工具来实现对数据的备份和恢复。

mongodump能够在Mongodb运行时进行备份,它的工作原理是对运行的Mongodb做查询,然后将所有查到的文档写入磁盘。但是存在的问题时使用mongodump产生的备份不一定是数据库的实时快照,如果我们在备份时对数据库进行了写入操作,则备份出来的文件可能不完全和Mongodb实时数据相等。

mongodump 进行热备份

mongodump工具使用说明:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

$ mongodump --help

Export MongoDB data to BSON files.

  

options:

  --help                   produce help message

  -v [ --verbose ]         be more verbose (include multiple times for more 

                           verbosity e.g. -vvvvv)

  --version                print the program's version and exit

  -h [ --host ] arg        mongo host to connect to ( <set name>/s1,s2 for 

                           sets)

  --port arg               server port. Can also use --host hostname:port

  --ipv6                   enable IPv6 support (disabled by default)

  -u [ --username ] arg    username

  -p [ --password ] arg    password

  --dbpath arg             directly access mongod database files in the given 

                           path, instead of connecting to a mongod  server - 

                           needs to lock the data directory, so cannot be used 

                           if a mongod is currently accessing the same path

  --directoryperdb         if dbpath specified, each db is in a separate 

                           directory

  --journal                enable journaling

  -d [ --db ] arg          database to use