我在大量Nodejs开发实践中,发现回滚是一个非常严谨的话题,我们应该重视这个回滚话题。我们不能祈祷上天程序不要出错,而忽略掉错误处理方案。
比如,我们在开发一个发布系统的过程中,有一系列的操作,数据库CRUD,FS操作项目文件,同时对gitlab的api进行操作。这个时候我们的顺序可能是这样的:
- 数据库插入一个项目并且返回一个项目ID
- 使用这个项目ID,通过FS操作,命名这个项目的文件夹为
project_${id}
- 将这个项目文件夹及一下所有的文件上传到一个FTP去
- 然后在gitlab中操作这个项目相关详情
我们来脑补下场景:
- 如果我们在第1步就出错了,数据库插入就出现问题,可能我们数据库突然挂掉,那么程序就会抛出错误,当然没关系,因为后续操作没有进行。
- 如果我们在第2步出现错误,这个文件夹是重名的,那么可能会抛出错误了,但是当时我们没有使用回滚,导致数据库已经插入,但是文件夹内容与我们想要的不匹配。
- 如果我们在第3步出错了,数据库已经插入,文件夹已命名,FTP突然挂掉,那么数据库出现了无效数据,文件也出现了无效数据。
- 如果我们在第4步出错了,其他都正确,那么我们是否因为前3步出现的操作,导致数据无法同步,文件无法同步,api操作无法同步
那么我们就多么尴尬啊。当然,我们可以通过捕获错误来进行相对应的错误处理。但是我们不知道我们会在哪一步出现而回滚对应的行为。经过我的总结,提出3种回滚模式:
- 事务回滚 (mysql, redis, mssql等)
- 物理回滚 (主要是fs操作等)
- api回滚
我们需要建立一套任务机制,在此机制上面实现2个概念:
- task:resolve 任务成功
- task:reject 任务失败回调
我们来看下以下的内容。
通用想法
说到任务机制,我们自然会想到如下的模式:
const task = new Tasker();
task.add(async () => {
await mysql.add({
a: 1,
b: 2
})
});
task.add(async () => {
fs.writeFileSync('/a', 'aaaaaa', 'utf8');
});
// ....
await task.run();
对,其实想法都是非常正确,再结合我们提出的概念,就变成了如下的写法:
task.add(async function resolve() {
fs.writeFileSync('/a', 'aaaaaa', 'utf8');
}, async function reject() {
fs.unlinkSync('/a');
})
确实我们是实现了简单的任务机制。但是我们是否觉得这样的写法非常麻烦,那么我们将引出我们今天的重点模块 ys-dbo
使用ys-dbo解决回滚问题
我们先来看一段代码:
const DBO = require('ys-dbo');
const dbo = new DBO();
// 这里我们假设已经安装了mysql模块
dbo.until(async thread => {
// 我们把之前的代码实现一下
const file = '/tmp/test.txt';
await mysql.begin();
await mysql.insert('table', {
a: 1,
b: 2
});
fs.writeFileSync(file, 'aaaaaa', 'utf8');
thread.on('beforeRollback', async () => fs.unlinkSync(file));
gitlab.fork('project');
thread.on('beforeRollback', async () => gitlab.deleteProject('project'));
}).then(...).catch(...)
从上面代码中我们完全可以看出没有任何task.add
的痕迹,取而代之的是beforeRollback
或者afterRollback
等事件。我们通过action+event
的模式将任务机制简化了。
所以我们可以看一个图:
上图明确描述了回滚的机制,我们通过一一对应注册的模式,来管理任务队列。
我现在发现很多同学不爱用回滚,可能嫌弃比较麻烦的写法,这样写出来的代码兼容性不会太好。但是我们要知道回滚其实是数据处于一致性状态的重要手段。我们要重视回滚,不在祈祷上天不要出错。
在我们公司,我也问过很多java开发的同学,很少有人用到回滚,我就很纳闷,作为一位开发工程师,不考虑严谨模式,这是不合格的,回滚也可以看出一个工程师的代码素养。
ys-dbo是什么?
大家不用刻意在意这个模块,毕竟是个人开发实践出来的模块,可能完善度不是很高,但是我会一直维护下去,因为毕竟自己的工作中也常用到。
npm i ys-dbo
喜欢的同学点个赞吧,感谢!