一、docker-compose 创建 mongodb 副本集
INFO
使用密码后 mongodb 就开启了认证模式,每个实例都需要拥有相同的 keyfile 才能加入副本集。而 windows 上不能挂载 mongodb 的目录,因此打算稍稍修改 mongodb 的镜像,将 keyfile 放在镜像中。
1.1 修改镜像
Dockerfile
:
FROM mongo
# 生成 keyfile
RUN mkdir -p /data/key \
&& openssl rand -base64 756 > /data/key/replica-set.key
# 修改 keyfile 权限
RUN chown mongodb:mongodb /data/key/replica-set.key \
&& chmod 400 /data/key/replica-set.key
INFO
容器中
mongodb
用户和组的 ID 都是 999,即也可以是chown 999:999 /data/key/replica-set.key
构建镜像:
docker build -t mongo-replica-set .
1.2 启动伪集群
创建网络:
docker network create local-net
compose-mongo.yml
:
version: '3.8'
services:
# 主节点
mongo0:
image: mongo-replica-set
restart: always
privileged: true
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
command: --replSet replica-set --keyFile /data/key/replica-set.key
# 副节点
mongo1:
image: mongo-replica-set
restart: always
privileged: true
ports:
- 27018:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
command: --replSet replica-set --keyFile /data/key/replica-set.key
# 仲裁节点
mongo2:
image: mongo-replica-set
restart: always
privileged: true
ports:
- 27019:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
command: --replSet replica-set --keyFile /data/key/replica-set.key
networks:
# 默认使用自己创建的网络
default:
external:
name: local-net
启动:
docker-compose -f compose-mongo.yml up -d
1.3 创建副本集
进入mongo0
容器进行连接:
# 连接
mongo
# 认证
use admin
db.auth('root', 'root')
INFO
成功返回 1 失败返回 0
初始化副本集:
rs.initiate()
INFO
无参初始化后,当前节点默认是
PRIMARY
节点
添加节点:
# 副节点
rs.add('mongo1:27017')
# 仲裁节点
rs.add('mongo2:27017', true)
查看副本集配置信息:
rs.conf()
查看副本集运行状态:
rs.status()
增加mongo0
的权重:
cfg = rs.conf()
# 修改权重
cfg.members[0].priority=5
# 重新配置
rs.reconfig(cfg)
INFO
仲裁节点的权重默认为 0,其它节点默认为 1。调高
mongo0
节点的权重后,如果mongo0
宕机,mongo1
会成为新主节点,当mongo0
恢复后会重新成为主节点。
1.4 验证副本集
切换节点查看同步状态:
rs.printReplicationInfo()
TIP
仅当创建了集合后副节点才会进行同步。
二、springboot 事务验证
2.1 连接
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
application.yml
:
spring:
data:
mongodb:
host: localhost
port: 27017
authentication-database: admin
username: root
password: root
database: test
replica-set-name: replica-set
INFO
库和集合需要提前创建好。
只连接主节点进行写操作。同时连接主节点和副节点需要注入不同的
mongoTemplate
分别进行读写。
2.2 事务配置
@Configuration
public class MongoConfig {
@Bean
public MongoTransactionManager mongoTransactionManager(MongoDatabaseFactory factory) {
return new MongoTransactionManager(factory);
}
}
2.3 测试
entity:
@Data
@Accessors(chain = true)
@Document("test_entity")
public class TestEntity {
private String id;
private Integer code;
}
service:
@Service
public class TestService {
@Autowired
private MongoTemplate mongoTemplate;
@Transactional
public List<String> test() {
List<String> idList = new ArrayList<>();
for (int i = -2; i < 2; i++) {
int code = 10 / i;
// int code = 10 / i + 3;
TestEntity entity = new TestEntity().setCode(code);
TestEntity latest = mongoTemplate.insert(entity);
idList.add(latest.getId());
}
return idList;
}
}
TIP
@Transactional
默认只在发生RuntimeException
和Error
时进行回滚。throws
checked
异常时自动回滚:@Transactional(rollbackFor = Exception.class)
try-catch
checked
异常时手动回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- GridFS 不支持事务。
controller:
@RestController
public class TestController {
@Autowired private TestService testService;
@GetMapping("/test")
public List<String> idList() {
return testService.test();
}
}
GET http://localhost:8080/test
发生RuntimeException
时全部失败。