如何在Golang中使用MongoDB的事务
- 一、Mongo中的事务
- 1.Mongo新特性
- 2.基于会话的事务
- 3.事务相关命令
- 二、搭建Mongo副本集
- 1. 安装MongoDB
- 2. 环境变量配置
- 3. 创建副本集目录
- 3.1 创建主节点相关目录
- 3.2 创建副节点相关目录
- 3.3 创建仲裁节点相关目录
- 4. 创建副本集认证的key文件
- 5 修改MongoDB配置文件
- 5.1 主节点配置文件
- 5.2 副节点配置文件
- 5.3 仲裁节点配置文件
- 6. 使用Systemd对Mongo服务进行管理
- 6.1 主节点配置
- 6.2 副节点配置
- 6.3 仲裁节点配置
- 7. 启动MongoDB服务
-
- 8. 创建用户,并初始化副本集
- 三、在Go代码中实现Mongo事务
-
一、Mongo中的事务
1.Mongo新特性
首先,我们必须知道的是,Mongo的事务的在版本4.0时的新特性,也就是说,如果Mongo的版本是在4.0之前的,那么是不支持事务的,因此,我们的Mongo需要是4.0以上的版本。
2.基于会话的事务
其次,Mongo的事务是比较有意思的,Mongo要开启事务支持,需要搭建副本集(Replica Sets)。而且,Mongo的事务是和会话(Session)相关联的,一个会话同一时刻只能开启一个事务操作,当一个会话断开的时候,这个会话中的事务也会结束。
3.事务相关命令
Mongo中的事务相关命令如下:
sess = db.getMongo().startSession()
sess.startTransaction()
sess.abortTransaction()
sess.commitTransaction()
sess.endSession()
二、搭建Mongo副本集
以下搭建副本集以Centos为例,并在同一个机子上进行搭建
1. 安装MongoDB
首先在MongoDB官网下载对应系统和版本的MongoDB包,如:
[root@vm1 ~]
解压tgz包到/usr/local/目录下,并给目录重命名一下
[root@vm1 ~]
[root@vm1 ~]
2. 环境变量配置
[root@vm1 ~]
在末尾添加一行:export PATH=$PATH:/usr/local/mongodb-4.4.10/bin
[root@vm1 ~]
3. 创建副本集目录
3.1 创建主节点相关目录
[root@vm1 ~]
[root@vm1 mongodb-4.4.10]
[root@vm1 mongodb-4.4.10]
[root@vm1 primary]
3.2 创建副节点相关目录
[root@vm1 primary]
[root@vm1 mongodb-4.4.10]
[root@vm1 mongodb-4.4.10]
[root@vm1 secondary]
3.3 创建仲裁节点相关目录
[root@vm1 secondary]
[root@vm1 mongodb-4.4.10]
[root@vm1 mongodb-4.4.10]
[root@vm1 arbiter]
4. 创建副本集认证的key文件
[root@vm1 arbiter]
[root@vm1 mongodb-4.4.10]
[root@vm1 mongodb-4.4.10]
5 修改MongoDB配置文件
5.1 主节点配置文件
[root@vm1 mongodb-4.4.10]
[root@vm1 primary]
添加内容如下:
systemLog:
destination: file
path: "/usr/local/mongodb-4.4.10/primary/logs/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb-4.4.10/primary/data"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb-4.4.10/primary/pid/mongod.pid"
net:
bindIp: 0.0.0.0
port: 27017
replication:
replSetName: "my-rs"
security:
keyFile: "/usr/local/mongodb-4.4.10/mongo.keyfile"
clusterAuthMode: "keyFile"
5.2 副节点配置文件
[root@vm1 primary]
[root@vm1 secondary]
添加内容如下:
systemLog:
destination: file
path: "/usr/local/mongodb-4.4.10/secondary/logs/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb-4.4.10/secondary/data"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb-4.4.10/secondary/pid/mongod.pid"
net:
bindIp: 0.0.0.0
port: 27018
replication:
replSetName: "my-rs"
security:
keyFile: "/usr/local/mongodb-4.4.10/mongo.keyfile"
clusterAuthMode: "keyFile"
5.3 仲裁节点配置文件
[root@vm1 secondary]
[root@vm1 arbiter]
添加内容如下:
systemLog:
destination: file
path: "/usr/local/mongodb-4.4.10/arbiter/logs/mongod.log"
logAppend: true
storage:
dbPath: "/usr/local/mongodb-4.4.10/arbiter/data"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/usr/local/mongodb-4.4.10/arbiter/pid/mongod.pid"
net:
bindIp: 0.0.0.0
port: 27019
replication:
replSetName: "my-rs"
security:
keyFile: "/usr/local/mongodb-4.4.10/mongo.keyfile"
clusterAuthMode: "keyFile"
6. 使用Systemd对Mongo服务进行管理
6.1 主节点配置
[root@vm1 arbiter]
添加内容如下
[Unit]
Description=mongodb primary
[Service]
ExecStart=/usr/local/mongodb-4.4.10/bin/mongod -f /usr/local/mongodb-4.4.10/primary/config/mongod.conf
ExecStop=/bin/kill -INT $MAINPID
PIDFile=/usr/local/mongodb-4.4.10/primary/pid/mongod.pid
[Install]
WantedBy=multi-user.target
添加为开机启动
[root@vm1 arbiter]
6.2 副节点配置
[root@vm1 arbiter]
添加内容如下
[Unit]
Description=mongodb secondary
[Service]
ExecStart=/usr/local/mongodb-4.4.10/bin/mongod -f /usr/local/mongodb-4.4.10/secondary/config/mongod.conf
ExecStop=/bin/kill -INT $MAINPID
PIDFile=/usr/local/mongodb-4.4.10/secondary/pid/mongod.pid
[Install]
WantedBy=multi-user.target
添加为开机启动
[root@vm1 arbiter]
6.3 仲裁节点配置
[root@vm1 arbiter]
添加内容如下
[Unit]
Description=mongodb arbiter
[Service]
ExecStart=/usr/local/mongodb-4.4.10/bin/mongod -f /usr/local/mongodb-4.4.10/arbiter/config/mongod.conf
ExecStop=/bin/kill -INT $MAINPID
PIDFile=/usr/local/mongodb-4.4.10/arbiter/pid/mongod.pid
[Install]
WantedBy=multi-user.target
添加为开机启动
[root@vm1 arbiter]
7. 启动MongoDB服务
7.1 启动节点
[root@vm1 arbiter]
7.2 查看节点状态
[root@vm1 arbiter]
8. 创建用户,并初始化副本集
[root@vm1 mongodb-4.4.10]
> use admin
> db.createUser({user:"root", pwd:"root", roles:["root"]})
> config={
"_id": "my-rs",
"members": [
{
"_id": 0,
"host": "127.0.0.1:27017",
"priority": 2
},
{
"_id": 1,
"host": "127.0.0.1:27018",
"priority": 1
},
{
"_id": 2,
"host": "127.0.0.1:27019",
"arbiterOnly": true
}
]
}
> rs.initiate(config)
> rs.status()
三、在Go代码中实现Mongo事务
1. 下载驱动包
直接执行下面的命令获取Golang的官方Mongo驱动包
go get -u go.mongodb.org/mongo-driver/mongo
2. 代码例子
使用事务时,特别要注意该用哪个context,在进行任何的db操作,不管是插入还是更新,都必须使用函数参数的那个sessionCtx,否则事务是无法生效的。另外在进行提交和回滚的时候,需要使用context.Background(),这是因为提交和回滚不应被context超时等因素影响。
package main
import (
"context"
"fmt"
"github.com/beego/beego/v2/core/logs"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
const (
user = "root"
pwd = "root"
hosts = "127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019"
mongoOpt = "replicaSet=my-rs"
auth = "admin"
timeout = time.Duration(3000) * time.Millisecond
)
type student struct {
Name string `bson:"name"`
Gender string `bson:"gender"`
Age int `bson:"age"`
}
func main() {
uri := fmt.Sprintf("mongodb://%s:%s@%s/%s?%s",
user, pwd, hosts, mongoOpt, auth)
opt := options.Client().ApplyURI(uri).SetSocketTimeout(timeout)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
client, err := mongo.Connect(ctx, opt)
if err != nil {
logs.Error("connect mongo failed, err:%s", err.Error())
return
}
err = client.Ping(ctx, nil)
if err != nil {
logs.Error("ping mongo failed, err:%s", err.Error())
return
}
database := "school"
collection := "student"
students := []interface{}{
student{
Name: "Michael",
Gender: "Male",
Age: 21,
},
student{
Name: "Alice",
Gender: "Female",
Age: 19,
},
}
if err = client.UseSession(ctx, func(sessionContext mongo.SessionContext) error {
if err := sessionContext.StartTransaction(); err != nil {
return err
}
if _, err := client.Database(database).Collection(collection).InsertMany(sessionContext, students); err != nil {
if err := sessionContext.AbortTransaction(context.Background()); err != nil {
logs.Error("mongo transaction rollback failed, %s", err.Error())
return err
}
return err
}
return sessionContext.CommitTransaction(context.Background())
}); err != nil {
logs.Error("insert failed, err:%s", err.Error())
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)