實踐數據回滾解決方案

我在大量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
複製代碼

喜歡的同窗點個贊吧,感謝!

相關文章
相關標籤/搜索