厚积薄发打卡Day90: MongoDB + RabbitMQ 构建消息推送功能(上)<环境搭建及MongoDB入门>

业务背景

消息系统需求实现

  1. 需要记录消息本身,以及消息发送对象
  2. 消息发送后,需要在客户端显示消息的已读、未读的提示。

思路

  1. 假如只是单纯消息发送,不管有无看到(类似 UDP连接),则直接创建消息表存消息即可。
  2. 但需要记录用过户已读、未读消息则需要多建用户消息记录表,同时向n个用户发送m条消息则需要在数据表中记录m*n条数据,发送消息的瞬间将有大量的性能损耗在数据库读写上,此时传统的关系型数据库则会严重影响整个系统的运行。
  3. 因为消息模块的要存储的数据量太大,普通MySQL读写消耗开销过大映像性能,所以要换能存储海量数据的数据库产品,MongoDB适合存储海量低价值的数据,正好符合消息模块的存储要求。
  4. 俗话说水滴石穿,考虑到系统的健壮性,用MongoDB存储消息数据,后期用户体量上来了,发送一条公告消息要往数据库里面写入大量的数据,即便MongoDB也支撑不下来瞬时写入百万,此时可以引入消息队列MQ,然后在Java后端系统上面,用异步多线程的方法,向消息队列MQ中发送消息,这样Web系统发布公告消息的时候就不占用数据库正常的CRUD操作。
  5. 系统消息保存在消息队列中,用它来做削峰填谷,系统消息最终还是要存储在数据库上面。于是我们可以这样设计,在用户登陆系统的时候,用异步线程从消息队列MQ中,接收该用户的系统消息,然后把系统消息存储在数据库中,最后消息队列MQ中的该条消息自动删除。

总结

使用MongoDB + RabbitMQ 构建消息推送功能

环境搭建

  1. 使用Docker镜像搭建提高效率

    docker入门:【狂神说Java】Docker最新超详细版教程通俗易懂

    1. Docker简介:

      Docker是一个开放源代码软件项目,让应用程序布署在软件容器下的工作可以自动化进行,借此在 Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。

    2. Docker特性:

      传统的软件开发与发布环境复杂,配置繁琐,经常有读者在微信上问:我的代码开发环境可以运行,一 旦部署到服务器上就运行不了了。这个问题很常见,也确实很烦人,但是问题总要解决,开发环境、 测试环境、生产环境,每个环节都有可能出现这样那样的问题,如果能够在各个环境中实现一键部署, 就会方便很多,例如一键安装linux、一键安装mysql、一键安装nginx等,docker彻底解决了这个问题。

    3. 现场搭建Docker环境:

      1. 安装

        #安装Docker
        yum install docker -y
        #启动Docker服务
        service docker start
        
      2. 因为Docker在线安装镜像是从国外的DockerHub网站下载文件,速度有限,所以得设置加速器,这里我们使用腾讯云加速器:

        打开/etc/docker/daemon.json文件,然后设置成如下内容:

        {
        	"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
        }
        
      3. 重新启动Docker服务,加速器才能生效

        service docker restart
        
  2. 使用Docker搭建MongoDB

    1. 执行命令,下载最新版本的MongoDB镜像

      docker pull mongo
      
    2. 创建/root/mongo/mongod.conf文件,然后在文件中添加如下内容:

      mkdir -p /root/mongo
      vim /root/mongo/mongod.conf
      
      net:
         port: 27017
         bindIp: "0.0.0.0"
      
      storage:
         dbPath: "/data/db"
         
      security:
        authorization: enabled
      
    3. 创建容器,为MongoDB分配500M内存

      docker run -it -d --name mongo --net=host \
      -v /root/mongo:/etc/mongo -m 500m \
      -e MONGO_INITDB_ROOT_USERNAME={用户名} \
      -e MONGO_INITDB_ROOT_PASSWORD={密码} \
      mongo --config /etc/mongo/mongod.conf
      
    4. 用Navicat连接MongoDB,检测是否可用。

  3. 使用Docker搭建RabbitMQ

    详见:docker实战系列之搭建rabbitmq

MongoDB 入门:

教程:MongoDB 教程

  1. MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。

    MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

    在这里插入图片描述

  2. 概念解析

    不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下表将帮助您更容易理解Mongo中的一些概念:

    SQL术语/概念MongoDB术语/概念解释/说明
    databasedatabase数据库
    tablecollection数据库表/集合
    rowdocument数据记录行/文档
    columnfield数据字段/域
    indexindex索引
    table joinsaggregate表连接
    primary keyprimary key主键,MongoDB自动将_id字段设置为主键
  3. MongoDB的增删改查:

    1. 增(插入文档):MongoDB 插入文档 | 菜鸟教程 (runoob.com)

      以下文档可以存储在 MongoDB 的 runoob 数据库 的 col 集合中:

      >db.col.insert({title: 'MongoDB 教程', 
          description: 'MongoDB 是一个 Nosql 数据库',
          by: '菜鸟教程',
          url: 'http://www.runoob.com',
          tags: ['mongodb', 'database', 'NoSQL'],
          likes: 100
      })
      

      以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

      查看已插入文档:

      > db.col.find()
      { "_id" : ObjectId("56064886ade2f21f36b03134"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
      > 
      
    2. 删(删除文档)MongoDB 删除文档 | 菜鸟教程 (runoob.com)

      db.collection.remove(
         <query>,
         {
           justOne: <boolean>,
           writeConcern: <document>
         }
      )
      

      参数说明:

      • query :(可选)删除的文档的条件。
      • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
      • writeConcern :(可选)抛出异常的级别
    3. 改(更新文档)MongoDB 更新文档 | 菜鸟教程 (runoob.com)

      我们在集合 col 中插入如下数据:

      >db.col.insert({
          title: 'MongoDB 教程', 
          description: 'MongoDB 是一个 Nosql 数据库',
          by: '菜鸟教程',
          url: 'http://www.runoob.com',
          tags: ['mongodb', 'database', 'NoSQL'],
          likes: 100
      })
      

      接着我们通过 update() 方法来更新标题(title):

      >db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
      WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })   # 输出信息
      > db.col.find().pretty()
      {
              "_id" : ObjectId("56064f89ade2f21f36b03136"),
              "title" : "MongoDB",
              "description" : "MongoDB 是一个 Nosql 数据库",
              "by" : "菜鸟教程",
              "url" : "http://www.runoob.com",
              "tags" : [
                      "mongodb",
                      "database",
                      "NoSQL"
              ],
              "likes" : 100
      }
      >
      

      可以看到标题(title)由原来的 “MongoDB 教程” 更新为了 “MongoDB”。

      以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

      >db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
      
    4. 查(查询文档)MongoDB 查询文档 | 菜鸟教程 (runoob.com)

      以下实例我们查询了集合 col 中的数据:

      > db.col.find().pretty()
      {
              "_id" : ObjectId("56063f17ade2f21f36b03133"),
              "title" : "MongoDB 教程",
              "description" : "MongoDB 是一个 Nosql 数据库",
              "by" : "菜鸟教程",
              "url" : "http://www.runoob.com",
              "tags" : [
                      "mongodb",
                      "database",
                      "NoSQL"
              ],
              "likes" : 100
      }
      

      除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档。

      MongoDB 与 RDBMS Where 语句比较

      如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

      操作格式范例RDBMS中的类似语句
      等于{<key>:<value>}db.col.find({"by":"菜鸟教程"}).pretty()where by = '菜鸟教程'
      小于{<key>:{$lt:<value>}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50
      小于或等于{<key>:{$lte:<value>}}db.col.find({"likes":{$lte:50}}).pretty()where likes <= 50
      大于{<key>:{$gt:<value>}}db.col.find({"likes":{$gt:50}}).pretty()where likes > 50
      大于或等于{<key>:{$gte:<value>}}db.col.find({"likes":{$gte:50}}).pretty()where likes >= 50
      不等于{<key>:{$ne:<value>}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50

      MongoDB AND 条件

      MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

      语法格式如下:

      >db.col.find({key1:value1, key2:value2}).pretty()
      
    5. 表连接 MongoDB关联(聚合)查询,关联集合筛选

      假设有:商品表goods 和 订单表orders,并具有一对多的关系:

      在这里插入图片描述

      查询所有商品对应的所有订单:

      //关联查询
      db.goods.aggregate([
              {
                  $lookup: {
                      from: "orders", // 要关联查询的集合
                      localField: "_id", // goods集合中的_id
                      foreignField: "goodsId", // 要查询的集合的 关联id
                      as: "child"
                  }
              }
          ])
      
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值