实践数据回滚解决方案

我在大量Nodejs开发实践中,发现回滚是一个很是严谨的话题,咱们应该重视这个回滚话题。咱们不能祈祷上天程序不要出错,而忽略掉错误处理方案。javascript

好比,咱们在开发一个发布系统的过程当中,有一系列的操做,数据库CRUD,FS操做项目文件,同时对gitlab的api进行操做。这个时候咱们的顺序多是这样的:java

  1. 数据库插入一个项目而且返回一个项目ID
  2. 使用这个项目ID,经过FS操做,命名这个项目的文件夹为project_${id}
  3. 将这个项目文件夹及一下全部的文件上传到一个FTP去
  4. 而后在gitlab中操做这个项目相关详情

咱们来脑补下场景:mysql

  1. 若是咱们在第1步就出错了,数据库插入就出现问题,可能咱们数据库忽然挂掉,那么程序就会抛出错误,固然不要紧,由于后续操做没有进行。
  2. 若是咱们在第2步出现错误,这个文件夹是重名的,那么可能会抛出错误了,可是当时咱们没有使用回滚,致使数据库已经插入,可是文件夹内容与咱们想要的不匹配。
  3. 若是咱们在第3步出错了,数据库已经插入,文件夹已命名,FTP忽然挂掉,那么数据库出现了无效数据,文件也出现了无效数据。
  4. 若是咱们在第4步出错了,其余都正确,那么咱们是否由于前3步出现的操做,致使数据没法同步,文件没法同步,api操做没法同步

那么咱们就多么尴尬啊。固然,咱们能够经过捕获错误来进行相对应的错误处理。可是咱们不知道咱们会在哪一步出现而回滚对应的行为。通过个人总结,提出3种回滚模式:git

  1. 事务回滚 (mysql, redis, mssql等)
  2. 物理回滚 (主要是fs操做等)
  3. api回滚

咱们须要创建一套任务机制,在此机制上面实现2个概念:github

  1. task:resolve 任务成功
  2. task:reject 任务失败回调

咱们来看下如下的内容。redis

通用想法

说到任务机制,咱们天然会想到以下的模式:sql

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();
复制代码

对,其实想法都是很是正确,再结合咱们提出的概念,就变成了以下的写法:shell

task.add(async function resolve() {
    fs.writeFileSync('/a', 'aaaaaa', 'utf8');
}, async function reject() {
    fs.unlinkSync('/a');
})
复制代码

确实咱们是实现了简单的任务机制。可是咱们是否以为这样的写法很是麻烦,那么咱们将引出咱们今天的重点模块 ys-dbo数据库

使用ys-dbo解决回滚问题

咱们先来看一段代码:npm

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是什么?

你们不用刻意在乎这个模块,毕竟是我的开发实践出来的模块,可能完善度不是很高,可是我会一直维护下去,由于毕竟本身的工做中也经常使用到。

项目地址:github.com/yskit/ys-db…

npm i ys-dbo
复制代码

喜欢的同窗点个赞吧,感谢!

相关文章
相关标签/搜索