最近需要验证一下mongodb的事务回滚,上网查了些资料,站在了巨人的肩膀上,自己总结整个安装和配置代码的过程,亲测有效,也为其他人少走一些坑,也方便自己日后查看。话不多说,开撸。
版本了解
0 当前稳定版本只是到了4.0.10,而开发版到了4.2.0-rc1
1 4.0.10 只支持副本集的回滚
2 MongoDB 4.0.x中,能够支持多文档事务。
3 spring和mongodb的jar包需要升级
Spring:5.1.1.RELEASE 以上 这里我采用 5.1.2.RELEASE
SpringDataMongoDB:2.1.1.RELEASE 以上 这里我采用2.1.2.RELEASE
java 操作方式:
使用spring的 MongoTemplate 来操作
副本集(Replica Set)是一组MongoDB实例组成的集群,也就是一主多从;
由一个主(Primary)服务器和多个备份(Secondary)服务器构成(可以在一台机器上面)
通过Replication(复制),将数据的更新由Primary推送到其他实例上,在一定的延迟之后,每个MongoDB实例维护相同的数据集副本。
该文采取在同一台机器上面安装两个mongodb,一主一从;
主节点: 192.168.10.128:20788
从节点: 192.168.10.128:20789
系统: Centos 7
软件: mongodb 4.0.10
https://blog.csdn.net/xyb0926/article/details/92080383
如果在同一台主机配置多台mongodb,建议不要配置环境变量,容易操作而且不会出现问题
port=27088 #端口
dbpath= /usr/mongodb/mongodb-4.0.10/db #数据库存文件存放目录
logpath= /usr/mongodb/mongodb-4.0.10/log/mongodb.log #日志文件存放路径
logappend=true #使用追加的方式写日志
fork=true #以守护进程的方式运行,创建服务器进程
maxConns=100 #最大同时连接数
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger #存储引擎,有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0 #设置成全部ip可以访问,这样就可以在windows中去连虚拟机的MongoDB,也可以设置成某个网段或者某个ip
noauth=true #不启用验证
加了一个服务,端口改成 27089
进入安装目录
cd /usr/mongodb_primary/mongodb-4.0.10/bin
在bin的目录下执行,启动服务
./mongod -f /usr/mongodb_primary/mongodb-4.0.10/mongodb.conf
在主节点创建root管理员账号
use admin
db.createUser( {user: "root",pwd: "123456",roles: [ { role: "root", db: "admin" } ]})
关闭
ps -ef|grep mongodb
kill -2 xxxx
在安装目录下,生成keyfiles文件
openssl rand -base64 756 > energy-rc.key
设置只读权限
chmod 400 energy-rc.key
修改主和从的配置文件,两个都一样
port=27088 #端口
dbpath= /usr/mongodb_primary/mongodb-4.0.10/db #数据库存文件存放目录
logpath= /usr/mongodb_primary/mongodb-4.0.10/log/mongodb.log #日志文件存放路径
logappend=true #使用追加的方式写日志
fork=true #以守护进程的方式运行,创建服务器进程
maxConns=100 #最大同时连接数
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger #存储引擎,有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0 #设置成全部ip可以访问,这样就可以在windows中去连虚拟机的MongoDB
#添加以下内容:
replSet=rs0 #复制集名称
auth=true #打开认证
keyFile=/usr/mongodb_primary/mongodb-4.0.10/energy-rc.key #启用key验证
#noauth=true #不启用验证
启动主:
cd /usr/mongodb_primary/mongodb-4.0.10/bin
./mongod -f /usr/mongodb_primary/mongodb-4.0.10/mongodb.conf
启动从:
cd /usr/mongodb_secondary1/mongodb-4.0.10/bin
./mongod -f /usr/mongodb_secondary1/mongodb-4.0.10/mongodb.conf
进入客户端:
cd /usr/mongodb_primary/mongodb-4.0.10/bin
./mongo --port 27088
验证登录:
use admin
db.auth('root','123456')
查看复制集状态
rs.status()
结果会显示--- 未收到replset配置
{
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}
开始定义配置信息,把两台节点加进来
var config={_id:'rs0',members:[{_id:0,host:'192.168.10.128:20788'},{_id:1,host:'192.168.10.128:20789'}]}
开始初始化复制集
rs.initiate(config)
初始化之后,查看配置信息,这是前面显示的是复制集
**rs0:SECONDARY**> rs.conf()
可以看到两个服务的信息
当你退出重新连接主节点的时候
use admin
db.auth('root','123456')
可以看到,当前节点为主了
这时候再查询配置的信息:
**rs0:PRIMARY**> db.isMaster()
结果可以看到两个服务的主从关系
先在主节点插入数据:
先用admin数据库和root账号登录;
use testdata
b.testdata.insert({"name":"tom"})
在从节点上查看是否已同步
登录从节点客户端;
cd /usr/mongodb_secondary1/mongodb-4.0.10/bin
./mongo --port 27089
rs0:SECONDARY> use admin
rs0:SECONDARY> db.auth('root','test123')
默认因为SECONDARY是不允许读写的,开启可以读写:
rs0:SECONDARY> db.getMongo().setSlaveOk();
显示所有数据库:
rs0:SECONDARY> show dbs # 这时可以看到所有的数据库,包括刚刚在主节点新建的 testdata 数据库
rs0:SECONDARY> use testdata
rs0:SECONDARY> db.testdata.find() # 查询testdata数据库中所有的文档
结果如下:
{ "name" : "tom" }
证明测试成功
为什么要创建一个新的数据库和新的数据库管理员,因为这个是给spring配置,也就是你的代码中连接操作的。
进入主节点
rs0:PRIMARY> use admin
rs0:PRIMARY> db.auth('root','123456')
创建数据库和数据库管理员:
rs0:PRIMARY> use mydata
rs0:PRIMARY> db.createUser( {user:"datauser", pwd:"123456",roles:[{role:"dbOwner",db:"mydata"}]})
spring-MongoSource.xml 文件
注意:
配置用户密码直接这样配置在标签上的credentials 属性上就可以了
网上有人说用以下这个用户验证,但是自己测试过没有连接成功,需要注意
所以我们采用以下的方式的连接配置mongodb
config.properties:
#config for mongoDB
mongo.username=datauser
mongo.password=123456
#mongo.host=192.168.161.128
#mongo.port=27088
mongo.replSet=192.168.161.128:27089
mongo.minConnectionsPerHost=10
mongo.threadsAllowedToBlockForConnectionMultiplier=4
mongo.connectTimeout=30000
mongo.maxWaitTime=3000
mongo.socketKeepAlive=false
mongo.socketTimeout=30000
mongo.maxConnectionIdleTime=0
mongo.maxConnectionLifeTime=0
mongo.heartbeatSocketTimeout=20000
mongo.heartbeatConnectTimeout=10000
mongo.minHeartbeatFrequency=3000
mongo.heartbeatFrequency=5000
mongo.database=pay
service层测试事务代码
如果涉及到多个事务,@Transactional 后面加上你要的事务的id名
@Override
@Transactional("mongoTransactionManager2")
public void testMonogo() throws Exception
{
// 执行mongo
Map mapData = new HashMap<>();
mapData.put("太阳", "this is a sun");
mongoTemplate.save(mapData,"col");
// 执行错误代码
throw new RuntimeException("error");
}