聊聊起源
在自己练手的小玩具功能不断复杂之后,
开始出现一个请求需要操作多个表的场景.
面对这个情况,
考虑到如果操作一个数据库的时候失败报错, 那之前操作的还需要手动恢复,
感觉会给业务代码里面掺杂很多复杂逻辑.
不利于后续开发,
经过研究之后, 发现事务回滚机制正好试用这个场景,
那高低研究一波.
代码改造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const mongoose = require("mongoose");
const session = await mongoose.startSession();
try { session.startTransaction();
await session.commitTransaction();
return resTry; } catch (error) { session.abortTransaction();
return resCatch; } finally { session.endSession(); }
|
代码改造后测试了一下,
当抛出异常, 代码也执行了 session.abortTransaction
,
不过之前写入数据库的数据并没有撤销.
经过查询资料之后发现,
mongodb 想要事务回滚必须要设置为副本集模式.
配置改造
登录服务器执行如下命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| // 创建一个名为 "mongodbnet" 的 Docker 网络,可以将多个容器连接到同一个网络中,使它们能够相互通信。 docker network create mongodbnet
// 查看 Docker 中的所有网络 docker network ls
// 创建 conf/mongod.keyfile (为副本集共用) openssl rand -base64 756 > /usr/local/mongo/conf/mongod.keyfile
// 创建 conf/mongod.conf (为副本集共用) vim /usr/local/mongo/conf/mongod.conf
security: authorization: enabled keyFile: /conf/mongod.keyfile
replication: replSetName: rs0
net: port: 27017 bindIp: 127.0.0.1
// 创建 mongod.conf.orig(为副本集共用)
security: authorization: enabled keyFile: /conf/mongod.keyfile
replication: replSetName: rs0
// 放开权限 chmod 600 /usr/local/mongo/conf/mongod.keyfile
// 启动容器 docker run \ --name mongo1 \ --net mongodbnet \ -p 27001:27017 \ -v /usr/local/mongo/mongod.conf.orig:/etc/mongod.conf.orig \ -v /usr/local/mongo/conf/mongod.conf:/conf/mongod.conf \ -v /usr/local/mongo/conf/mongod.keyfile:/conf/mongod.keyfile \ -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \ -e MONGO_INITDB_ROOT_USERNAME=yourusername \ -e MONGO_INITDB_ROOT_PASSWORD=yourpassword \ -d --restart=always mongo:4.2 \ --replSet rs0 \ --auth
docker run \ --name mongo2 \ --net mongodbnet \ -p 27002:27017 \ -v /usr/local/mongo/mongod.conf.orig:/etc/mongod.conf.orig \ -v /usr/local/mongo/conf/mongod.conf:/conf/mongod.conf \ -v /usr/local/mongo/conf/mongod.keyfile:/conf/mongod.keyfile \ -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \ -e MONGO_INITDB_ROOT_USERNAME=yourusername \ -e MONGO_INITDB_ROOT_PASSWORD=yourpassword \ -d --restart=always mongo:4.2 \ --replSet rs0 \ --auth
docker run \ --name mongo3 \ --net mongodbnet \ -p 27003:27017 \ -v /usr/local/mongo/mongod.conf.orig:/etc/mongod.conf.orig \ -v /usr/local/mongo/conf/mongod.conf:/conf/mongod.conf \ -v /usr/local/mongo/conf/mongod.keyfile:/conf/mongod.keyfile \ -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \ -e MONGO_INITDB_ROOT_USERNAME=yourusername \ -e MONGO_INITDB_ROOT_PASSWORD=yourpassword \ -d --restart=always mongo:4.2 \ --replSet rs0 \ --auth
// 考虑关闭三个 mongodb 容器,然后按照先开启主节点容器、再开启父节点容器的顺序启动。(选做) docker stop mongo3 mongo2 mongo1
docker restart mongo1 docker restart mongo2 docker restart mongo3
// 进入主 mongo 容器 docker exec -it mongo1 bash
chmod 600 /conf/mongod.keyfile
// 查看通用配置文件 cat etc/mongod.conf.orig
// 进入 mongo 数据库 mongo -u yourusername -p yourpassword --authenticationDatabase admin
// 初始化副本集
> rs.initiate() > rs.initiate({ \_id: "rs0", members: [ { _id: 0, host: "mongo1:27017" }, { _id: 1, host: "mongo2:27017" }, { _id: 2, host: "mongo3:27017" } ]})
rs0:PRIMARY> rs.status() rs0:PRIMARY> rs.isMaster()
// 关联副本 rs0:PRIMARY> rs.add("mongo2:27017") rs0:PRIMARY> rs.add("mongo3:27017")
// ===== 备份操作 ===== // 启动容器 -v /usr/local/mongo/conf/mongod.conf:/conf/mongod.conf \ -v /usr/local/mongo/mongod.conf.orig:/etc/mongod.conf.orig \ --keyFile /conf/mongod.keyfile \ --config /conf/mongod.conf \
// 矫正时区 docker cp /usr/share/zoneinfo/Asia/Shanghai mongo1:/etc/localtime docker cp /usr/share/zoneinfo/Asia/Shanghai mongo2:/etc/localtime docker cp /usr/share/zoneinfo/Asia/Shanghai mongo3:/etc/localtime
// 容器内操作配置 mongo --config /conf/mongod.conf --keyFile /conf/mongod.keyfile --replSet rs0
// 需要携带账号密码么? rs.add("mongo2:27017", { username: "yourusername", password: "yourpassword", authenticationDatabase: "admin" }) // =================
|
库库一顿配置,
不好使…
裂开了,
后面再说吧
数据迁移
后面如果副本集配置好之后,
那么就需要将旧的数据库数据迁移到新的副本集数据库之中.
操作待学习…
后续
事务回滚的优先级不是那么高,
先暂时搁置一波了,
太浪费时间了.
真在实际中遇到这种问题,
到时候再抱住运维大哥大腿好了.
那么再完善这个机制好了.