Mongodb

目录

1.2 MongoDB简介

 linux安装


1.2 MongoDB简介

MongoDB 是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是 NoSQL 数据库产品中的一种。是最
像关系型数据库( MySQL )的非关系型数据库。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫 BSON ,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB 中的记录是一个文档,它是一个由字段和值对( fifield:value )组成的数据结构。 MongoDB 文档类似于 JSON 对象,即一个文档认
为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

 linux安装

1)先到官网 Download MongoDB Community Server | MongoDB 下载压缩包 mongod - linux - x86_64 - 4.0.10.tgz
2 )上传压缩包到 Linux 中,解压到当前目录:
3 )移动解压后的文件夹到指定的目录中:
4 )新建几个目录,分别用来存储数据和日志:
5 )新建并修改配置文件
配置文件的内容如下:
tar -xvf mongodb-linux-x86_64-4.0.10.tgz
mv mongodb-linux-x86_64-4.0.10 /opt/module/mongodb
#数据存储目录
mkdir -p /opt/module/mongodb/single/data/db
#日志存储目录
mkdir -p /opt/module/mongodb/single/log
vi /opt/module/mongodb/single/mongod.conf

配置文件的内容如下:

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
   # 将 MongoDB 发送所有日志输出的目标指定为文件
   destination: file
   # mongod 或 mongos 应向其发送所有诊断日志记录信息的日志文件的路径
   path: "/opt/module/mongodb/single/log/mongodb.log"
   # 当 mongos 或 mongod 实例重新启动时,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true

# Where and how to store data.
storage:
   # The directory where the mongod instance stores its data. 
   dbPath: "/opt/module/mongodb/single/data/db"
   # 启用或禁用持久性日志以确保数据文件保持有效和可恢复
   journal:
      enabled: true

processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护程序模式
   fork: true

net:
   # 服务实例绑定的IP,0.0.0.0表示监听所有(所有主机都可以访问)
   bindIp: 0.0.0.0
   port: 27017

启动MongoDB服务

/opt/module/mongodb/bin/mongod -f /opt/module/mongodb/single/mongod.conf

选择和创建数据库,本机终端执行mongodb语句进入数据库命令行

mongo --host=192.168.48.102

show dbs
数据库名可以是满足以下条件的任意 UTF-8 字符串。
不能是空字符串( "")
不得含有 ' ' (空格 ) . $ / \ \0 ( 空字符 )
应全部小写。
最多 64 字节。
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
admin
从权限的角度来看,这是 "root" 数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特
定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
confifig : Mongo 用于分片设置时, confifig 数据库在内部使用,用于保存分片的相关信息。

选择和创建数据库的语法格式:
use 数据库名称
​​​​​​​如果数据库不存在则自动创建
use articledb
查看有权限查看的所有的数据库命令
show dbs 或show databases
查看当前正在使用的数据库命令
db
删除数据库
db.dropDatabase()
​​​​​​​
3.3 集合操作
3.3.1 集合的显式创建
db.createCollection("my")
查看当前库中的表:show tables命令
​​​​​​​
show collections
或
show tables
集合删除
db.collection.drop() 或db.my.drop()

3.4 文档基本 CRUD
文档( document )的数据结构和 JSON 基本一样。
所有存储在集合中的数据都是 BSON 格式。
3.4.1 文档的插入
#插入单条
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明 媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null})
#插入多条
db.comment.insertMany([ {"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我 他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08- 05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"}, {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔 悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"}, {"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船 长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"}, {"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯 撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"}, {"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫 嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08- 06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"} ]);
db.comment.find()

//文档的基本查询
db.comment.find()
//条件查询
db.comment.find({articleid:"100001"})
//单个条件查询
db.comment.findOne({articleid:"100001"})
//条件查询+筛选查询
db.comment.find({userid:"1003"},{userid:1,nickname:1}) 
//条件查询+筛选查询并去掉 id列
db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0})

db.comment.drop()
//插入时指定了 _id ,则主键就是该值。
//如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。
//因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理,测试的时候可以不处理
try{
    db.comment.insertMany([{
        "_id": "1",
        "articleid": "100001",
        "content": "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我 他。",
        "userid": "1002",
        "nickname": "相忘于江湖",
        "createdatetime": new Date("2019-08- 05T22:08:15.522Z"),
        "likenum": NumberInt(1000),
        "state": "1"
    }, {
        "_id": "2",
        "articleid": "100001",
        "content": "我夏天空腹喝凉开水,冬天喝温开水",
        "userid": "1005",
        "nickname": "伊人憔 悴",
        "createdatetime": new Date("2019-08-05T23:58:51.485Z"),
        "likenum": NumberInt(888),
        "state": "1"
    }, {
        "_id": "3",
        "articleid": "100001",
        "content": "我一直喝凉开水,冬天夏天都喝。",
        "userid": "1004",
        "nickname": "杰克船 长",
        "createdatetime": new Date("2019-08-06T01:05:06.321Z"),
        "likenum": NumberInt(666),
        "state": "1"
    }, {
        "_id": "4",
        "articleid": "100001",
        "content": "专家说不能空腹吃饭,影响健康。",
        "userid": "1003",
        "nickname": "凯 撒",
        "createdatetime": new Date("2019-08-06T08:18:35.288Z"),
        "likenum": NumberInt(2000),
        "state": "1"
    }, {
        "_id": "5",
        "articleid": "100001",
        "content": "研究表明,刚烧开的水千万不能喝,因为烫 嘴。",
        "userid": "1003",
        "nickname": "凯撒",
        "createdatetime": new Date("2019-08- 06T11:01:02.521Z"),
        "likenum": NumberInt(3000),
        "state": "1"
    }]);
} catch(e) {
    print(e);
}

修改功能

//覆盖修改  将id为1的数据 修改为 字段只有likenum
db.comment.update({_id:"1"},{likenum:NumberInt(1001)})
//局部修改 修改某一个字段的值
db.comment.update({_id:"2"},{$set:{likenum:NumberInt(1001)}})

//默认只修改第一条数据
 db.comment.update({userid:"1003"},{$set:{nickname:"凯撒2"}}) 
 //修改所有符合条件的数据
	db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})

//字段某个值加1
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

        删除功能

//根据条件删除
db.comment.remove({_id:"1"})
//全部删除
db.comment.remove({})
//然后重新插入
try{
    db.comment.insertMany([{
        "_id": "1",
        "articleid": "100001",
        "content": "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我 他。",
        "userid": "1002",
        "nickname": "相忘于江湖",
        "createdatetime": new Date("2019-08- 05T22:08:15.522Z"),
        "likenum": NumberInt(1000),
        "state": "1"
    }, {
        "_id": "2",
        "articleid": "100001",
        "content": "我夏天空腹喝凉开水,冬天喝温开水",
        "userid": "1005",
        "nickname": "伊人憔 悴",
        "createdatetime": new Date("2019-08-05T23:58:51.485Z"),
        "likenum": NumberInt(888),
        "state": "1"
    }, {
        "_id": "3",
        "articleid": "100001",
        "content": "我一直喝凉开水,冬天夏天都喝。",
        "userid": "1004",
        "nickname": "杰克船 长",
        "createdatetime": new Date("2019-08-06T01:05:06.321Z"),
        "likenum": NumberInt(666),
        "state": "1"
    }, {
        "_id": "4",
        "articleid": "100001",
        "content": "专家说不能空腹吃饭,影响健康。",
        "userid": "1003",
        "nickname": "凯 撒",
        "createdatetime": new Date("2019-08-06T08:18:35.288Z"),
        "likenum": NumberInt(2000),
        "state": "1"
    }, {
        "_id": "5",
        "articleid": "100001",
        "content": "研究表明,刚烧开的水千万不能喝,因为烫 嘴。",
        "userid": "1003",
        "nickname": "凯撒",
        "createdatetime": new Date("2019-08- 06T11:01:02.521Z"),
        "likenum": NumberInt(3000),
        "state": "1"
    }]);
} catch(e) {
    print(e);
}
3.5 文档的分页查询
3.5.1
db.comment.find({userid:"1003"}).explain()
// 查看所有索引
db.comment.getIndexes()
// 对 userid 字段建立单一索引:
db.comment.createIndex({userid:1})
// :对 userid 和 nickname 同时建立复合(Compound)索引:
db.comment.createIndex({userid:1,nickname:-1})
// 删除 comment 集合中 userid 字段上的升序索引:
db.comment.dropIndex({userid:1})
// 删除 spit 集合中所有索引。
db.collection.dropIndexes()
// 查看根据userid查询数据的情况:
db.comment.find({userid:"1003"}).explain()
​​​​​​​ 统计、分页、排序查询查询
//按条件统计查询
db.comment.count()
//按条件统计查询
db.comment.count({userid:"1003"})
//查询3条数据跳过第4条
db.comment.find().limit(3).skip(4);
//1为 升序-1为降序
db.comment.find().sort({userid:-1,likenum:1})

复杂查询

/1、复杂查询
//正则查询内容包含开水的
db.comment.find({content:/开水/});
//2、比较查询
// 大于: field > value 
db.comment.find({ likenum : { $gt: 700 }}) 
// 小于: field < value
db.comment.find({ likenum : { $lt: 700 }}) 
 // 大于等于: field >= value 
db.comment.find({ likenum : { $gte: 700 }})
// 小于等于: field <= value
db.comment.find({ likenum : { $lte: 700 }}) 
// 不等于: field != value
db.comment.find({ likenum : { $ne: 700 }}) 
//3、包含查询
//包含使用$in操作符。 示例:查询评论的集合中userid字段包含1003或1004的文档
db.comment.find({userid:{$in:["1003","1004"]}})
//不包含使用$nin操作符。 示例:查询评论集合中userid字段不包含1003和1004的文档
db.comment.find({userid:{$nin:["1003","1004"]}})
//4、条件查询
//查询评论集合中likenum大于等于700 并且小于2000的文档:
db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})
//:查询评论集合中userid为1003,或者点赞数小于1000的文档记录
db.comment.find({$or:[{userid:"1003"},{likenum:{$lt:1000}}]})

常用指令

选择切换数据库:use articledb 
插入数据:db.comment.insert({bson数据})
查询所有数据:db.comment.find(); 
条件查询数据:db.comment.find({条件}) 
查询符合条件的第一条记录:db.comment.findOne({条件}) 
查询符合条件的前几条记录:db.comment.find({条件}).limit(条数) 
查询符合条件的跳过的记录:db.comment.find({条件}).skip(条数) 
修改数据:db.comment.update({条件},{修改后的数据}) 或db.comment.update({条件},{$set:{要修改部分的字段:数据}) 
修改数据并自增某字段值:db.comment.update({条件},{$inc:{自增的字段:步进值}}) 
删除数据:db.comment.remove({条件}) 
统计查询:db.comment.count({条件}) 
模糊查询:db.comment.find({字段名:/正则表达式/}) 
条件比较运算:db.comment.find({字段名:{$gt:值}}) 
包含查询:db.comment.find({字段名:{$in:[值1,值2]}})或db.comment.find({字段名:{$nin:[值1,值2]}}) 
条件连接查询:db.comment.find({$and:[{条件1},{条件2}]})或db.comment.find({$or:[{条件1},{条件2}]})

4 索引-Index

索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排

序支持有效的相等匹配和基于范围的查询操作。此外, MongoDB 还可以使用索引中的排序返回排序结果。
MongoDB 索引使用 B 树数据结构(确切的说是 B-Tree MySQL B+Tree
db.comment.find({userid:"1003"}).explain()
// 查看所有索引
db.comment.getIndexes()
// 对 userid 字段建立单一索引:
db.comment.createIndex({userid:1})
// :对 userid 和 nickname 同时建立复合(Compound)索引:
db.comment.createIndex({userid:1,nickname:-1})
// 删除 comment 集合中 userid 字段上的升序索引:
db.comment.dropIndex({userid:1})
// 删除 spit 集合中所有索引。
db.collection.dropIndexes()
// 查看根据userid查询数据的情况:
db.comment.find({userid:"1003"}).explain()

微服务模块搭建

1 )搭建项目工程 article pom.xml 引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.itcast</groupId>
    <artifactId>article</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>

</project>

2)创建application.yml

spring:
#数据源配置
  data:
    mongodb:
    # 主机地址
      host: 192.168.48.102
      # 数据库
      database: articledb
        # 默认端口是27017
      port: 27017 #也可以使用uri连接
      #uri: mongodb://192.168.40.134:27017/articledb

创建实体类 cn.itcast.article.po.Comment

package cn.itcast.article.po;


import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * 文章评论实体类
 */
//把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
//@Document(collection="mongodb 对应 collection 名")
// 若未加 @Document ,该 bean save 到 mongo 的 comment collection
// 若添加 @Document ,则 save 到 comment collection
@Document(collection = "comment")//可以省略,如果省略,则默认使用类名小写映射集合
//复合索引
 @CompoundIndex( def = "{'userid': 1, 'nickname': -1}")
public class Comment implements Serializable {
    //主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
    @Id
    private String id;//主键
    //该属性对应mongodb的字段的名字,如果一致,则无需该注解
    @Field("content")
    private String content;//吐槽内容
    private Date publishtime;//发布日期
    //添加了一个单字段的索引
    @Indexed
    private String userid;//发布人ID
    private String nickname;//昵称
    private LocalDateTime createdatetime;//评论的日期时间
    private Integer likenum;//点赞数
    private Integer replynum;//回复数
    private String state;//状态
    private String parentid;//上级ID
    private String articleid;

    //getter and setter.....
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getPublishtime() {
        return publishtime;
    }

    public void setPublishtime(Date publishtime) {
        this.publishtime = publishtime;
    }

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public LocalDateTime getCreatedatetime() {
        return createdatetime;
    }

    public void setCreatedatetime(LocalDateTime createdatetime) {
        this.createdatetime = createdatetime;
    }

    public Integer getLikenum() {
        return likenum;
    }

    public void setLikenum(Integer likenum) {
        this.likenum = likenum;
    }

    public Integer getReplynum() {
        return replynum;
    }

    public void setReplynum(Integer replynum) {
        this.replynum = replynum;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getParentid() {

        return parentid;
    }

    public void setParentid(String parentid) {
        this.parentid = parentid;
    }

    public String getArticleid() {
        return articleid;
    }

    public void setArticleid(String articleid) {
        this.articleid = articleid;
    }

    @Override
    public String toString() {
        return "Comment{" +
                "id='" + id + '\'' +
                ", content='" + content + '\'' +
                ", publishtime=" + publishtime +
                ", userid='" + userid + '\'' +
                ", nickname='" + nickname + '\'' +
                ", createdatetime=" + createdatetime +
                ", likenum=" + likenum +
                ", replynum=" + replynum +
                ", state='" + state + '\'' +
                ", parentid='" + parentid + '\'' +
                ", articleid='" + articleid + '\'' +
                '}';
    }
}

创建接口

cn.itcast.article.dao.CommentRepository
package cn.itcast.article.dao;

/**
 * @Author sxd
 * @create 2023/2/18 23:20
 */
import cn.itcast.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
//评论的持久层接口
public interface CommentRepository extends MongoRepository<Comment,String> {

    Page<Comment> findByParentid(String parentid,Pageable pageable);
}
下创建类
cn.itcast.article.service.CommentService
package cn.itcast.article.service;

import cn.itcast.article.dao.CommentRepository;
import cn.itcast.article.po.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author sxd
 * @create 2023/2/18 23:25
 */
@Service
public class CommentService {

    //注入dao
    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 保存一个评论
     *
     * @param comment
     */
    public void saveComment(Comment comment) {
//如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
//设置一些默认初始值。。。
//调用dao
        commentRepository.save(comment);
    }

    /**
     * 更新评论
     *
     * @param comment
     */
    public void updateComment(Comment comment) {
//调用dao
        commentRepository.save(comment);
    }

    /**
     * 根据id删除评论
     *
     * @param id
     */
    public void deleteCommentById(String id) {
//调用dao
        commentRepository.deleteById(id);
    }

    /**
     * 查询所有评论
     *
     * @return
     */
    public List<Comment> findCommentList() {
//调用dao
        return commentRepository.findAll();
    }

    /**
     * 根据id查询评论
     *
     * @param id
     * @return
     */
    public Comment findCommentById(String id) {
//调用dao
        return commentRepository.findById(id).get();
    }

    public Page<Comment> findCommentListByParentid(String parentid, int page, int size) {
        return commentRepository.findByParentid(parentid, PageRequest.of(page, size));
    }
  public void updateCommentLikenum(String id){
//        查询条件
        Query query=Query.query(Criteria.where("_id").is(id));
      Update update = new Update();
      update.inc("likenum");
        mongoTemplate.updateFirst(query,update,Comment.class);
  }

}

3)新建Junit测试类,测试保存和查询所有:

cn.itcast.article.service.CommentServiceTest
package cn.itcast.article.service;

import cn.itcast.article.po.Comment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Author sxd
 * @create 2023/2/18 23:39
 */

@RunWith(SpringRunner.class)
@SpringBootTest
public class CommentServiceTest {

    @Autowired(required = false)
    CommentService commentService;

    /**
     * 保存一个评论
     */
    @Test
    public void testSaveComment() {
        Comment comment = new Comment();
        comment.setArticleid("100000");
        comment.setContent("测试添加的数据");
        comment.setCreatedatetime(LocalDateTime.now());
        comment.setUserid("1003");
        comment.setNickname("凯撒大帝");
        comment.setState("1");
        comment.setLikenum(0);
        comment.setReplynum(0);
        commentService.saveComment(comment);
    }

    /**
     * 查询所有数据
     */
    @Test
    public void testFindAll() {
        List<Comment> list = commentService.findCommentList();
        System.out.println(list);
    }

    /**
     * 测试根据id查询
     */
    @Test
    public void testFindCommentById() {
        Comment comment = commentService.findCommentById("1");
        System.out.println(comment);
    }

    @Test
    public void testFindCommentListByParentid() {
        Page<Comment> page = commentService.findCommentListByParentid("3", 1, 2);
        System.out.println(page.getTotalElements());
        System.out.println(page.getContent());
    }

    //根据id使值递增
    @Test
    public void testUpdateCommentLikenum() {
        commentService.updateCommentLikenum("1");
    }
}

1. MongoDB 副本集 - Replica Sets

1.1 简介

MongoDB 中的副本集(Replica Set)是一组维护相同数据集的 mongod 服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。

也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库当掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载

冗余和数据可用性

复制提供冗余并提高数据可用性。 通过在不同数据库服务器上提供多个数据副本,复制可提供一定级别的容错功能,以防止丢失单个数据库服务器。

在某些情况下,复制可以提供增加的读取性能,因为客户端可以将读取操作发送到不同的服务上, 在不同数据中心维护数据副本可以增加分布式应用程序的数据位置和可用性。 还可以为专用目的维护其他副本,例如灾难恢复,报告或备份。

MongoDB 中的复制

副本集是一组维护相同数据集的 mongod 实例。 副本集包含多个数据承载节点和可选的一个仲裁节点。 在承载数据的节点中,一个且仅一个成员被视为主节点,而其他节点被视为次要(从)节点。

主节点接收所有写操作。 副本集只能有一个主要能够确认具有 {w:"most"} 写入关注的写入; 虽然在某些情况下,另一个 mongod 实例可能暂时认为自己也是主要的。主要记录其操作日志中的数据集的所有 更改,即 oplog。

辅助(副本)节点复制主节点的oplog并将操作应用于其数据集,以使辅助节点的数据集反映主节点的数据 集。 如果主要人员不在,则符合条件的中学将举行选举以选出新的主要人员。

主从复制和副本集区别

主从集群和副本集最大的区别就是副本集没有固定的”主节点”;整个集群会选出一个”主节点”,当其挂掉后,又在剩下的从节点中选中其他节点为主节点,副本集总有一个活跃点 (主、primary) 和一个或多个备份节点 (从、secondary)

1.2 副本集的三个角色

副本集有两种类型三种角色

两种类型:

  • 主节点(Primary)类型:数据操作的主要连接点,可读写
  • 次要(辅助、从)节点(Secondary)类型:数据冗余备份节点,可以读或选举

三种角色:

  • 主要成员(Primary):主要接收所有写操作。就是主节点
  • 副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要配置)。是默认的一种从节点类型
  • 仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

 搭建副本集

ps aux|grep mongodb

kill -9 编号
#创建主节点数据和日志目录
mkdir -p /opt/module/mongodb/replica_sets/myrs_27017/log
mkdir -p /opt/module/mongodb/replica_sets/myrs_27017/data/db
#新建配置文件
vim /opt/module/mongodb/replica_sets/myrs_27017/mongod.conf

systemLog:
  #MongoDB发送所有日志输出的目标指定为文件
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/opt/module/mongodb/replica_sets/myrs_27017/log/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
  logAppend: true
storage:
  #mongod实例存储其数据的目录,storage.dbPath设置仅适用于mongod。
  dbPath: "/opt/module/mongodb/replica_sets/myrs_27017/data/db"
  journal:
    #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
    enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  #指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
  pidFilePath: "/opt/module/mongodb/replica_sets/myrs_27017/log/mongod.pid"
net:
  #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
  #bindIpAll:true
  #服务实例绑定的IP
  bindIp: localhost,192.168.48.102
  #bindIp
  #绑定的端口
  port: 27017
replication:
  #副本集的名称
  replSetName: myrs
#启动主节点 
mongod -f /opt/module/mongodb/replica_sets/myrs_27017/mongod.conf

#---------myrs
#从节点
mkdir -p /opt/module/mongodb/replica_sets/myrs_27018/log
mkdir -p /opt/module/mongodb/replica_sets/myrs_27018/data/db

vim /opt/module/mongodb/replica_sets/myrs_27018/mongod.conf


systemLog:
  #MongoDB发送所有日志输出的目标指定为文件
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/opt/module/mongodb/replica_sets/myrs_27018/log/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
  logAppend: true
storage:
  #mongod实例存储其数据的目录,storage.dbPath设置仅适用于mongod。
  dbPath: "/opt/module/mongodb/replica_sets/myrs_27018/data/db"
  journal:
    #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
    enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  #指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
  pidFilePath: "/opt/module/mongodb/replica_sets/myrs_27018/log/mongod.pid"
net:
  #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
  #bindIpAll:true
  #服务实例绑定的IP
  bindIp: localhost,192.168.48.102
  #bindIp
  #绑定的端口
  port: 27018
replication:
  #副本集的名称
  replSetName: myrs
  
mongod -f /opt/module/mongodb/replica_sets/myrs_27018/mongod.conf

#---------myrs
#从节点
mkdir -p /opt/module/mongodb/replica_sets/myrs_27019/log
mkdir -p /opt/module/mongodb/replica_sets/myrs_27019/data/db

vim /opt/module/mongodb/replica_sets/myrs_27019/mongod.conf

systemLog:
  #MongoDB发送所有日志输出的目标指定为文件
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/opt/module/mongodb/replica_sets/myrs_27019/log/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
  logAppend: true
storage:
  #mongod实例存储其数据的目录,storage.dbPath设置仅适用于mongod。
  dbPath: "/opt/module/mongodb/replica_sets/myrs_27019/data/db"
  journal:
    #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
    enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
  #指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
  pidFilePath: "/opt/module/mongodb/replica_sets/myrs_27019/log/mongod.pid"
net:
  #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
  #bindIpAll:true
  #服务实例绑定的IP
  bindIp: localhost,192.168.48.102
  #bindIp
  #绑定的端口
  port: 27019
replication:
  #副本集的名称
  replSetName: myrs
  
  
  
  mongod -f /opt/module/mongodb/replica_sets/myrs_27019/mongod.conf
  
  
#  连接节点
  ./mongo --host=192.168.48.102 --port=27017
#初始化副本
rs.initiate()
#来查看相应的信息
rs.conf()
rs.status()

// 将27018的副本节点添加到副本集中
rs.add("192.168.48.102:27018")
// 将27019的仲裁节点添加到副本集中
rs.addArb("192.168.48.102:27019")

 如果出现以下提示,代表某个副本没启动

 

/opt/module/mongodb/bin/mongod -f /opt/module/mongodb/replica_sets/myrs_27019/mongod.conf 
#创建数据库
use articledb

db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Aoi","createdatetime":new Date()})

 db.comment.find()

然后再起一个连接 

#启动副本节点
/opt/module/mongodb/bin/mongo --host 192.168.48.102 --port 27018
 show dbs

查询后

发现,不能读取集合的数据。当前从节点只是一个备份,不是奴隶节点,无法读取数据,写当然更不
行。
因为默认情况下,从节点是没有读写权限的,可以增加读的权限,但需要进行设置。
设置读操作权限:
设置为奴隶节点,允许在从成员上运行读的操作
rs.slaveOk() #或rs.slaveOk(true)

 设置为false后权限关闭

/opt/module/mongodb/bin/mongo --host 192.168.48.102 --port 27019

rs.slaveOk()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ONLYYD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值