• MongoDB入门实践


    MongoDB入门实践#

    简单介绍MongoDB,包括MongoDB的使用场景、和MySQL的对比、安装部署、Java客户端访问及总结

    MongoDB?#

    我们遵循需求驱动技术的原则,通过一个场景来引入MongoDB,在现行业务需求下考虑下面三个问题:

    • 为什么要使用MongoDB?
    • MongoDB是一个什么样的产品?
    • 它能做什么?

    Situation(场景)##

    以公司站点报告业务场景(当前其实已换成hdfs):

    业务流程###

    • 从Server获取站点日志;
    • 日志分析后入MySQL库(8~9个字段,日期和多个维度字段和多个指标字段),每天数据量大约50w;
    • 依照维度字段、指标字段、日期(一般是每天)聚合查询,查询到的结果集(前1000条)存入Redis供前端展现;
    • 目前每天展示的报告实际是当天凌晨通过离线计算(相对时间较长)得到的结果。

    运行状态###

    • 数月时间运行后,MySQL库当中的数据量倍增,整个数据库的查询效率大大下降;
    • Redis的内存占用逐渐上升,并大量占用虚拟内存,导致服务器崩溃。
    • 并且由于Redis本身并不支持类似关系数据库的分页动作,只能存储少量数据作为前端展现,而不能一页一页展示整个结果集查询的结果。

    Problem(问题)##

    原有的解决方案(MySQL+Redis)

    • MySQL存储的数据量太大导致查询效率太低;
    • 把Redis当作存储使用,导致对虚拟内存占用太高;
    • Redis本身不支持关系型数据库的分页,实际展现数据并不完整。

    MongoDB特性

    • 大数据量存储,单实例TB级别
    • 高性能持久化数据:支持内存数据模型(减少IO),支持索引;
    • 高可用性(副本集):自动故障切换(automatic failover),数据备份(data redundancy);
    • 自动扩容:自动分片,副本集保证最终一致性、低延迟高流量。

    如此看来,MongoDB太强大了,似乎一种招招要了MySQL命的感觉,不过千万别这么想,毕竟术业有专攻!
    那现在就让我们来看看MongoDB的庐山真面目。

    先睹为快#

    插播一段广告,这里引用官方网站上MongoDB的查询示例比较下MySQL和MongoDB。

    MongoDB & MySQL查询比较

    • MySQL查询(SELECT _id,name,address FROM users WHERE age>18 LIMIT 5)
      sql-select
    • MongoDB查询(db.users.find( { age: { $gt: 18 } }, { name: 1, address: 1 } ).limit(5))
      mongodb-find

    有没有一种他们俩长的真像的感觉,没错你答对了,MongoDB被称作是最像关系型数据库的NOSQL数据库。

    How To Use#

    温馨提示

    • MongoDB存在企业版和社区版,企业版是收费版本(咱是穷人,自然不用收费版了)
    • 推荐安装64位
    • 推荐Linux下安装
    • Windows版本可用于调试

    官方网站##

    官网
    官网ORG

    下载##

    • 选择Current,Previous,Development
    • 选择Windows,Linux,Max OS X,Solaris
    • 选择下载格式

    文档##

    • 选择下载在线
    • 选择文档版本(2.6)
    • 选择文档格式

    安装&启动&关闭##

    Linux

    以Linux ReadHat为例

    安装

    • 创建文件mongdb.repo,路径:/etc/yum.repos.d/mongodb.repo
    • 配置mongdb.repo:
      64位:
    [mongodb]
    name=MongoDB Repository
    baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
    gpgcheck=0
    enabled=1
    

    32位:

    name=MongoDB Repository
    baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/i686/
    gpgcheck=0
    enabled=1
    
    • yum安装完整版: sudo yum install -y mongodb-org

    启动

    • selinux开启MongoDB tcp端口: semanage port -a -t mongod_port_t -p tcp 27017
    • 关闭SELINUX: SELINUX=disabled
    • 启动:sudo service mongod start
    • client: 执行mongo命令即可

    关闭

    • sudo service mongod stop
    • 进入mongo的窗口:use admin; db.shutdownServer()

    Windows 64位

    安装

    • 查看windows版本:wmic os get osarchitecture**
    • windows msi或zip(解压即可,比如目录:D:Program Filesmongodb)
    • 将bin目录加入到classpath

    启动

    • 解压目录下创建两级目录:datadb,datalog
    • 启动server(mongod,mongos(分片集群客户端))
      mongod.exe --dbpath "D:Program Filesmongodbdata"(如果路径中存在空格,请使用""引用路径)
    • client(* driver,mongo)
      mongo

    关闭

    • Ctrl+C
    • 进入mongo的窗口:use admin; db.shutdownServer()

    一般情况下,对于开发人员,我们更加关心MongoDB的Driver,和Mysql一样,它自然是多语言版的,作为Java开发人员,我们介绍MongoDB Java Driver。

    MongoDB Java Driver#

    获取Driver(pom)##

            <dependency>
                <groupId>org.mongodb</groupId>
                <artifactId>mongo-java-driver</artifactId>
                <version>2.13.0</version>
            </dependency>
    

    CRUD##

    我们以java代码方式操作MongoDB,然后用图形化的工具查看结果.

    insert###

    • 插入文档记录:{"name" : "someone" , "age" : 18 , "gender" : 1 , "address" : { "country" : "china" , "city" : "shanghai"}}
        @Test
        public void insert() throws Exception {
            // 新建客户端.
            MongoClient client = new MongoClient("127.0.0.1", 27017);
            // 获取DB.
            DB db = client.getDB("testDB");
            // 获取文档集.
            DBCollection collection = db.getCollection("demo");
            // 一行记录.
            // json: {"name" : "someone" , "age" : 18 , "gender" : 1 , "address" : { "country" : "china" , "city" : "shanghai"}}
            BasicDBObject user = new BasicDBObject("name", "someone")
                    .append("age", 18)
                    .append("gender", 1)
                    .append("address", new BasicDBObject("country", "china").append("city", "shanghai"));
    
            System.out.println(collection.insert(user));
            // 关闭客户端
            client.close();
        }
    

    insert-demo

    query###

    • 查询 条件:{ "name" : "someone"}的结果集
        @Test
        public void query() throws Exception {
            // 新建客户端.
            MongoClient client = new MongoClient("127.0.0.1", 27017);
            // 获取DB.
            DB db = client.getDB("testDB");
            // 获取文档集.
            DBCollection collection = db.getCollection("demo");
            // 条件: { "name" : "someone"}
            BasicDBObject match = new BasicDBObject("name", "someone");
            // 执行查询并打印结果集列表.
            System.out.println(collection.find(match).toArray());
            // 关闭客户端
            client.close();
        }
    

    insert-demo

    update###

    • 更新 条件: {"name" : "someone"} set: {"age": 28}
        @Test
        public void update() throws Exception {
            // 新建客户端.
            MongoClient client = new MongoClient("127.0.0.1", 27017);
            // 获取DB.
            DB db = client.getDB("testDB");
            // 获取文档集.
            DBCollection collection = db.getCollection("demo");
            // 条件.
            // json: {"name" : "someone"}
            BasicDBObject match = new BasicDBObject("name", "someone");
    
            // set:{"age": 28}
            BasicDBObject updatedValue = new BasicDBObject();
            updatedValue.put("age", 28);
            DBObject updateSetValue = new BasicDBObject("$set", updatedValue);
    
            // 执行更新并打印.
            //update api: DBObject q, DBObject o, boolean upsert, boolean multi.
            //upsert:若为true,没有找到匹配的记录时会执行新增一条记录,false则不做任何处理.
            //multi:若为false,表示只更新查询到的一条记录,true则表示更新所有匹配记录.
            System.out.println(collection.update(match, updateSetValue, false, true));
            // 关闭客户端
            client.close();
        }
    

    update-demo

    delete###

    • 删除 条件:{"name" : "someone"}
        @Test
        public void delete() throws Exception {
            // 新建客户端.
            MongoClient client = new MongoClient("127.0.0.1", 27017);
            // 获取DB.
            DB db = client.getDB("testDB");
            // 获取文档集.
            DBCollection collection = db.getCollection("demo");
            // 条件.
            // json: {"name" : "someone"}
            BasicDBObject match = new BasicDBObject("name", "someone");
            // 删除匹配记录.
            System.out.println(collection.remove(match));
            // 关闭客户端
            client.close();
        }
    

    delete-demo

    常用Api##

    常用类###

    • MongoClient 客户端连接抽象
    • DB 文档库
    • DBCollection 文档集
    • DBObject 文档对象基类
    • BasicDBObject 基础文档对象
    • BasicDBList 基础文档列表对象

    常用方法###

    • DBCollection: find(),update(),insert(),remove(), MongoDB大部分操作数据有关的Api都是基于此类.
    • MongoClient: getDB(), close()
    • DB: getCollection()
    • DBObject: put()
    • BasicDBObject: append()
    • BasicDBList: add()

    第三方封装(Third Party Frameworks and Libraries)##

    基于MongoDB的driver,有很多第三方封装的包,比如:

    • Spring MongoDB
      spring-mongodb
    • Jongo
      JONGO

    大多数框架都支持以POJO的方式开发基于MongoDB的应用!

    MongoDB & MySQL#

    Indicator MongoDB MySQL
    大数据支持 较强 一般
    ACID 部分支持 全部
    SQL特性 非结构化,支持部分SQL语言特性 完全支持SQL语言规范,标准化,交互性强
    扩展 自动扩展 有一定的硬件成本,需要第三方程序
    应用灵活性 一般

    MongoDB与MySQL是互补的关系
    MongoDB没有全面的ACID支持,因此不能将有事务场景的业务底层存储从MySQL改为NOSQL

    MongoDB最佳实践(不全)#

    • 版本更新
    • 采用Replicaton Sets(副本集)部署
    • 采用64位系统部署
    • 默认开启journaling日志
    • 谨慎分片sharding
    • 不要当做Sql数据库使用
    • 明确数据需要的一致性和可靠性
    • 按照真实业务场景全面测试
    • 采用固定的Schema设计(某个DBCollection下的文档结构一致)
    • 采用索引(和其它关系型数据使用索引的意义是一致的)

    QA#

  • 相关阅读:
    Kubernetes实战(第二版)----第1章 Kubernetes简介
    Kubernetes应用程序开发认证(CKAD)学习指南-第3章 配置
    Kubernetes应用程序开发认证(CKAD)学习指南-第2章 核心概念
    Kubernetes应用程序开发认证(CKAD)学习指南-第1章 考试详情和考试资源
    Stream Processing with Apache Flink中文版-- 第11章 接下来学什么
    Stream Processing with Apache Flink中文版-- 第10章 操作Flink和流式应用程序
    Stream Processing with Apache Flink中文版-- 第8章 与外部系统的读写交互
    Stream Processing with Apache Flink中文版-- 第7章 有状态操作符和应用程序
    Stream Processing with Apache Flink中文版-- 第6章 基于时间和窗口的操作符
    Stream Processing with Apache Flink中文版--第5章 DataStream API
  • 原文地址:https://www.cnblogs.com/fangfan/p/4997761.html
Copyright © 2020-2023  润新知