欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MongoDB副本集使用

程序员文章站 2022-05-08 15:01:46
...

MongoDB副本集使用

前言

mongodb副本集是个好东西,本文主要说明mongodb副本集的原理、功能以及如何与后端程序对接。

概述

为了适应越来越多的访问量,单台服务器已经不太顶了,即使这台服务器的性能很强。因此,就出现了集群的概念。所谓集群,说的是有好几个相同功能的服务器,一起提供服务,通过前端的负载均衡服务器或者是后端程序的操作,将访问量分流,压力分发之后,每台服务器都能平稳工作。更重要的是,当其中一台服务器崩溃之后,另外的服务器能正常提供服务,不至于整个业务崩溃。

MongoDB副本集使用

在mongodb中,也有解决类似问题的方案——副本集

所谓mongodb副本集,指的是N个mongodb服务器工作在同一个组的内时该组的叫法,与上图的集群有点不一样的是,mongodb副本集里的节点有主从之分,虽然都是对外提供服务,但是主节点能提供读写功能,而从节点只能提供读的功能。
MongoDB副本集使用
你可能会注意到,primary和secondary节点也有talk,并且你可能会有疑问,主从节点是按照什么来指定的?这里就涉及到了mongo副本集的基本算法——Bully算法,这里读者可以自行百度,就不过分赘述,简单说一下过程(参考raft算法):

最初的时候,大家都是从节点,但是突然有一天,其中有个节点发起了选举,鉴于友谊,每个节点都必须选择赞成。此时发起投票的节点就检查票数,当它发现赞成大于1/2时,它就升级为主节点并且告诉定时告诉其它节点,我是boss,你们不能选举,都听我的。为啥票数不是100%,因为可能由于网络故障等种种问题,主节点没收到某些票。当票数小于1/2时,那么大家就当无事发生,等待下一个节点提出选举。
MongoDB副本集使用
raft算法

此时,对主节点的操作,主节点会及时同步到从节点(参考mysql的两阶段提交),这样就实现了多服务器的数据一致了。

两阶段提交

总的来说,集群还是副本集都是为了提高服务器的可用性

说了这么多的原理,那么接下来讲讲当有了一个副本集之后,我们的项目去使用它。

对接流程

准备

系统环境:ubuntu 16.04

可用节点:192.168.1.100:8003,192.168.2.101:8004

仲裁者:192.168.1.100:8005

后端环境:spring-framework,IDEA

mongodb搭建:mongodb副本集搭建

需求

当一个项目需要接入mongodb服务器时,需要考虑下列问题

(1)后端程序如何连接mongodb

(2)后端程序与mongodb的传输的数据格式

(3)后端如何接入mongodb集群

单节点连接

对于第一个问题,spring框架已经为我们提供了方法,只需通过配置application.yml文件,将需要连接的mongodb服务器节点加入即可。

参考配置如下

server:
  # 通用配置
  port: 9000
  servlet:
    context-path: /mongo
spring:
  profiles:
    #执行模块
    active: mongo
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
---
# mongoDB模块
spring:
  profiles: mongo
  data:
    mongodb:
      # 未设置账号密码
      uri: mongodb://192.168.1.100:8003/Test
      # 有账号密码
      uri: mongodb://user:aaa@qq.com:8003/Test

(2)对于第二个问题,spring中也有具体的类去实现对mongodb数据库的增删改查操作,我写了三个层来做测试

实现如图
MongoDB副本集使用
1)controller层与前端交互

public class MongoController {

    @Autowired
    private MongoService mongoService;

    @PostMapping
    public void setUser(@RequestBody UserPo user) {
        mongoService.addUser(user);
    }

    @GetMapping
    public Object getUser() {
       return mongoService.getUser();
    }
}

2)service层

@Service
public interface MongoService {

    /**
     * 添加用户
     * @param user
     */
    void addUser(UserPo user);

    /**
     * 查看所有用户
     * @return
     */
    Object getUser();
}

3)impl层具体实现service及与数据库交互

@Service
@Slf4j
public class MongoServiceImpl implements MongoService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void addUser(UserPo user) {
        mongoTemplate.insert(user, "test");
    }

    @Override
    public Object getUser() {
        List<Object> objects = new ArrayList<>();
        FindIterable findIterable = mongoTemplate.getCollection("test").find();
        MongoCursor<UserPo> cursor = findIterable.iterator();
        while(cursor.hasNext()) {
          objects.add(cursor.next());
        }
        return objects;
    }
}

4)用于接收前端发送数据的userPo类

@Data
public class UserPo {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     *id
     */
    private Object id;
}

通过前端发送的读写api请求可以发现,后端与数据库之间的数据是按照Json格式传递的。

副本集连接

后端程序如何接入mongodb集群

在接入集群前,务必确保以下几点

(1)确保所有的mongodb节点都开着

(2)进入主节点查看所有节点状态

(3)若指定读节点中只有从节点,确保开启从节点的读权限

(1)思考

(1)若后端程序需要读写功能,那么必须确保连接在主节点上

(2)因为主节点可能会发生故障转移,转移后的主节点ip就变了,那么后端的连接地址就不能固定

(3)改变连接节点的工作必须由后端完成

(2)实现

搭建结构
MongoDB副本集使用

在mongodb的副本集中,不仅仅主从节点之间存在心跳机制,主节点和连接它的客户端之间也存在心跳机制,即定时发送一个心跳来确保对方还在。

spring框架中有负责监听、连接mongodb主节点的类以及定义的方法

在impl中的两个方法中添加节点池

{
    List<ServerAddress> serverAddresses = new ArrayList<>();
    ServerAddress address1 = new ServerAddress("192.168.1.100", 8003);
    ServerAddress address2 = new ServerAddress("192.168.2.101", 8004);
    serverAddresses.add(address1);
    serverAddresses.add(address2);
    MongoClient client = new MongoClient(serverAddresses);
}

(3)测试

(1)关闭主节点

当读写都确定没有问题之后,可以尝试关闭主节点,此时后端程序的会发出报告,并在一定时间(secondary节点变成主节点之后)连接上新的主节点。

(2)重新将关闭节点打开

重新打开新的节点之后,往主节点中进行写操作,并查看从节点数据是否同步成功。

test:SECONDARY> use Test
switched to db Test
test:SECONDARY> db.test.find()

到这里,mongodb的副本集与项目的对接基本完成,但是还可以进行下一步优化,将集群的读写进行分离。在Mongodb类中有一个ReadPreference方法可以实现读操作只在从节点上进行,这样处理之后,可以降低主节点的压力,减少主节点挂掉的风险。
参考资料

相关标签: mongodb