1. 程式人生 > >支付系統轉賬過程中併發交易引起的分散式死鎖問題

支付系統轉賬過程中併發交易引起的分散式死鎖問題

死鎖

死鎖的規範定義:集合中的每一個程序都在等待只能由本集合中的其他程序才能引發的事件,那麼該組程序是死鎖的。從廣義上講,這裡的程序指的是一個執行單元。

問題描述

假設【賬戶A】給 【賬戶B】轉賬 500 元,在程式中的轉賬邏輯如下:
1. 開啟事務
2. 【賬戶A】的餘額減去 500 元
3. 【賬戶B】的餘額增加 500 元
4. 提交事務

在叢集環境下,在 server1、server2 服務上都部署了支付模組,在該環境下可能會出現如下的場景:

  1. 在 server1 上執行【賬戶A】給【賬戶B】轉賬 500 元;
  2. 在 server2 上執行【賬戶B】給【賬戶A】轉賬 500 元;

以上兩個轉賬行為同時執行,那麼在執行到轉賬邏輯的第三步的時候,server1 會請求對【賬戶B】進行加鎖,server2 會請求對【賬戶A】進行加鎖,由於此時的【賬戶A】已由 server1進行鎖定,【賬戶B】已由 server2進行鎖定,此時就會產生死鎖問題。

解決方案

在併發程式設計中,我們經常遇到三個問題原子性問題、可見性問題、有序性問題。見Java程式設計:併發程式設計的3個特性

通過上面的問題描述我們可以發現,在一個轉賬的過程中【賬戶A】、【賬戶B】的執行是有序的,但是在多個轉賬過程中【賬戶A】、【賬戶B】的執行是無序的。該問題類似併發程式設計的有序性問題,我們可以通過如下方式解決改問題:

在系統中對所有的賬戶進行排序:
【賬戶A】、【賬戶B】、【賬戶C】、【賬戶D】、【賬戶E】、【賬戶F】

在 server1 上執行【賬戶A】給【賬戶B】轉賬 500 元的邏輯:
1. 開啟事務
2. 【賬戶A】的餘額減去 500 元
3. 【賬戶B】的餘額增加 500 元
4. 提交事務

在 server2 上執行【賬戶B】給【賬戶A】轉賬 500 元的邏輯:
1. 開啟事務
2. 【賬戶A】的餘額增加 500 元
3. 【賬戶B】的餘額減去 500 元
4. 提交事務

將賬戶進行排序,保證轉賬過程中【賬戶A】始終先於【賬戶B】,這樣就可以避免產生死鎖問題。

解決方案有好多中,這裡只提出我認為相對簡單的一種方案,而且也是也在一線網際網路公司廣泛使用的一種方案。如有不正之處,歡迎批評指正。