文章目录

  • 一、 前言
  • 二、简介
  • 三、实践
  • 1. 准备工作
  • 2. 启动服务
  • 3. 创建副本集
  • 四、Spring 事务测试
  • 1. 搭建


一、 前言

Mongo 的安装 请看前文 。
本文主要是在Spring 中使用mongo时需要使用事务(Mongo在4.0之后的版本开始支持事务)。但是Mongo 支持事务需要开启副本集。所以这里搭建一下副本集并且继承在Spring中。

二、简介

副本集(Replica Set)是一组MongoDB实例组成的集群,由一个主(Primary)服务器和多个备份(Secondary)服务器构成。通过Replication,将数据的更新由Primary推送到其他实例上,在一定的延迟之后,每个MongoDB实例维护相同的数据集副本。通过维护冗余的数据库副本,能够实现数据的异地备份,读写分离和自动故障转移。

也就是说如果主服务器崩溃了,备份服务器会自动将其中一个成员升级为新的主服务器。使用复制功能时,如果有一台服务器宕机了,仍然可以从副本集的其他服务器上访问数据。如果服务器上的数据损坏或者不可访问,可以从副本集的某个成员中创建一份新的数据副本。

早期的MongoDB版本使用master-slave,一主一从和MySQL类似,但slave在此架构中为只读,当主库宕机后,从库不能自动切换为主。目前已经淘汰master-slave模式,改为副本集,这种模式下有一个主(primary),和多个从(secondary),只读。支持给它们设置权重,当主宕掉后,权重最高的从切换为主。在此架构中还可以建立一个仲裁(arbiter)的角色,它只负责裁决,而不存储数据。此架构中读写数据都是在主上,要想实现负载均衡的目的需要手动指定读库的目标server。

官方文档地址:https://docs.mongodb.com/manual/replication/

三、实践

1. 准备工作

  1. 本机已经搭建好Mongo数据库。具体搭建过程请看这里。所以搭建过程本文不再叙述。当前目录如下
  2. 本机使用虚拟机,所以开启三个端口27017、27018、27019 三个端口的服务作为伪集群模式。
  3. conf目录创建三个端口的配置文件。
  4. 27017端口配置文件内容如下。要保证dbpath、logpath 配置下的目录结构存在。其中27018、27019 端口的配置文件和27017配置文件的差异就是端口号即数据存放目录、日志存放目录的不同
dbpath = ../data/27017 # 数据文件存放目录  
logpath = ../log/27017/mongodb.log # 日志文件存放目录  
port = 27017  # 端口  
directoryperdb = true  # 让每个库都有一个单独文件夹
fork = true		# 以后台运行方式启动
bind_ip = 0.0.0.0 # 开放所有ip或者开放指定ip,默认127.0.0.1。不开放远程连接不上
wiredTigerCacheSizeGB = 1 # 允许占用最大内存
replSet = rs  #副本集的名称

2. 启动服务

  1. 启动三个端口的服务。切换到mongo安装的bin目录下,启动服务
./mongod -f ../conf/mongo_27017.conf 
./mongod -f ../conf/mongo_27018.conf 
./mongod -f ../conf/mongo_27019.conf

3. 创建副本集

  1. 任选一台服务器连接 进入admin库 执行副本集初始化操作

    一定要注意,只有返回的ok值是1才是成功。
use admin
conf={
        "_id" : "rs",
        "members" : [
                {
                        "_id" : 0,
                        "host" : "192.168.44.137:27017"
                },
                {
                        "_id" : 1,
                        "host" : "192.168.44.137:27018"
                },
                {
                        "_id" : 2,
                        "host" : "192.168.44.137:27019"
                }
        ]
}

rs.initiate(conf)
  1. 查看副本集
db.isMaster()

注: 当要查看从节点数据时,如果出错,
这是因为从节点默认情况下是拒绝读取的,因此需开启读取功能

rs.slaveOk()

四、Spring 事务测试

1. 搭建

  1. yml 配置如下
spring:
 data:
    mongodb:
      uri: mongodb://192.168.44.137:27017/tx_test
      option:
        max-connection-per-host: 100
        max-wait-time: 120000
        threads-allowed-to-block-for-connection-multiplier: 10
        connect-timeout: 10000
        socket-keep-alive: false
        socket-timeout: 0
  1. 连接如下
  2. mongodb 事务处理 mongodb事务机制_mongodb 事务处理

  3. 测试类如下
@SpringBootTest
@RunWith(SpringRunner.class)
public class MongoTest {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    public void mongo(){
        User user = new User();
        user.setId(0);
        user.setName("张三");
        mongoTemplate.save(user, "user");
        int i = 10/0;
        user.setId(1);
        user.setName("李四");
        mongoTemplate.save(user, "user");
    }
}
  1. 执行结果如下
  2. mongodb 事务处理 mongodb事务机制_数据_02

  3. 清空tx_test.user表,并开启事务如下。再次执行
@SpringBootTest
@RunWith(SpringRunner.class)
public class MongoTest {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    // 需要指定是Mongo的数据源
    @Transactional(value = "MONGO_TRANSACTION_MANAGER", propagation = Propagation.REQUIRED)
    public void mongo() {
        User user = new User();
        user.setId(0);
        user.setName("张三");
        mongoTemplate.save(user, "user");
        int i = 10 / 0;
        user.setId(1);
        user.setName("李四");
        mongoTemplate.save(user, "user");
    }
}

库中没有数据,事务生效。

注: @Transactional 和 TransactionTemplate 默认都不是使用Mongo的数据源,所以需要手动指定。

可以通过下面的方式创建 TransactionTemplate 数据源。具体请看这里有详细代码描述。

mongodb 事务处理 mongodb事务机制_mongodb 事务处理_03