我們如何在Adyen做出架構決策 - Adyen

banq發表於2021-11-12

在 Adyen,我們有一種非常務實的方法來解決問題。因此,我們使用簡單的工具來取得出色的成果。

本部落格的目標是向您介紹我們在擴充套件系統時面臨的挑戰、我們如何應對這些挑戰,以及我們的系統因這些決定而呈現的樣子。特別是,我們將關注自主開發的解決方案與開源軟體之間的選擇。

在部落格的第一部分,我們將討論與我們的邊緣服務相關的這些主題,在第二部分,我們將對我們的會計和報告層做同樣的事情。

與其僅僅解釋我們的架構看起來如何,我們認為解釋為什麼我們的架構看起來會很有趣。在 Adyen,我們堅信賦予開發人員責任。這意味著負責系統的設計和實施以及該系統的安全和維護。因為我們系統的設計是由同時值班的工程師完成的。這些工程師在決定如何構建某些東西時是強有力的貢獻者,這有時會導致違反直覺的結果。

 

是自己構建本土解決方案還是選擇開源軟體?

Adyen 的新加入者經常對我們自己構建東西的某些情況感到驚訝。因此,我們認為在瀏覽我們的架構時,討論其中一些選擇會很有趣。有關我們自己建立銀行的極端示例,請觀看有關我們為何建立自己的銀行的簡短視訊

當我們面臨挑戰時,建議的解決方案通常是引入新工具或框架,或者在內部編寫一些東西。從 Adyen 的角度來看,自己編寫一些東西會給你更多的靈活性,但與開源替代方案相比,它會花費更多的時間並且可能具有更少的功能。

由於更好的文件和更大的社群,開源選項的可用性可能更高,但它可能更復雜,因為我們不需要額外的功能,並投資培訓需要使用它的人員。開源選項的安全性可能會更好,因為很多人都審查過它,但攻擊面也幾乎總是更大。

 

對供應商解決方案的看法

許多企業也會考慮供應商解決方案,我們也是。但是,我們希望專注於我們系統中的核心流程,對於這些流程,我們從不選擇專有解決方案,因為我們希望擁有完全控制權。

我們購買而不是構建,如果用例是外圍的,它不必是實時的,我們不必嵌入它,或者如果它是一個很好的價值主張。這方面的一個例子是我們的一些 KYC 背景調查員。當然,避免鎖定是這裡的一個重要考慮因素。

 

Adyen架構

Adyen 從事處理付款業務。我們收到商家的付款;我們將該付款傳送給第三方(例如信用卡公司),然後返回結果。這種情況每秒發生數百次,24/7。我們還跟蹤所有交易,以便我們可以在從銀行收到錢後將錢轉給商家。當然,我們也會向我們的商家提供報告。

我們每年為此花費數千億歐元。在過去的幾年裡,我們推出了其他產品,例如髮卡銀行Adyen for Platforms,這有助於平臺業務,如拼車或市場。我們在一個平臺上完成所有這些工作,在一個儲存庫 (monorepo) 中,幾乎完全用 Java 編寫。

我們的系統分為幾個部分,它們的功能相對獨立。它們沿著業務領域劃分。例如,我們有一部分以支付處理為中心,另一部分以銀行為中心。在資料層,它們被捆綁在一起。相同的設計原則適用於每個子系統。因此,雖然我們在本部落格中主要介紹了支付處理,但架構總體上是相似的。

商家傳送的付款將到達我們的邊緣層。這裡我們會做同步處理,如果需要聯絡支付方式,再將結果返回給商家。可用性和低延遲在這裡至關重要。同時,我們將此付款傳送到我們的後端系統,我們將其儲存在我們的會計系統中。準確性和可靠性是這部分系統的關鍵優先事項。最後,支付在我們的資料處理層結束,吞吐量成為一個主要問題。我們將逐一介紹這些層,討論我們為塑造它們所做的選擇。

 

邊緣服務

對我們系統的每個 API 呼叫都首先通過我們的邊緣服務。付款可以來自支付終端移動應用程式、直接 API 呼叫或我們託管支付頁面。支付接受層 (PAL) 是我們邊緣層中的一項關鍵服務。所有付款都通過它。

此應用程式會將付款傳送到我們的其他內部服務。這些其他服務可以是風險引擎、用於儲存或生成迴圈支付令牌的服務,或用於計算哪個連線將導致最高授權率的服務。它還將聯絡(通過中介服務)處理付款的合作伙伴付款方式或方案。

一個重要的設計特點是所有支付都在 PAL 處被抽象化,因此係統可以將它們視為平等。當然,它們之間是有區別的。有些會有額外的後設資料(對於銷售點交易,這可能是處理它們的終端的 ID)。但是,它們都通過相同的系統並儲存在相同的資料庫中。

處理初始設計的工程師已經在以前的支付公司獲得了經驗。在該公司中,進入系統的付款會在邊緣層保留一些狀態。如果新的付款會修改原始付款,例如退款,則可以立即處理,因為所有必需的資訊都已儲存在邊緣層中。

這種設定的問題是雙重的。應用程式不能停機維護或崩潰而不影響我們處理事務的能力。另一個問題是新機器無法立即處理與舊應用程式相同的卷。某些事務需要轉到特定例項。應用程式中的狀態使每個例項都是唯一的。

 

無狀態服務

退後一步,可以看出為什麼我們在 Adyen 採取了不同的做法。系統這部分的優先順序是高可用和低延遲。我們應該始終能夠接受付款並儘快處理它們。我們決定非同步處理修改,而不是將狀態保留在我們的邊緣層中,從而使邊緣層保持無狀態。

因此,任何 PAL 例項都可以在不影響我們處理付款的能力的情況下關閉,並且新的 PAL 可以立即與其他已經執行的 PAL 一樣有效。這使我們的水平縮放線性。換句話說,如果一個 PAL 每秒可以處理 X 筆付款,那麼兩個 PAL 每秒可以處理 2X 筆付款。該機制自公司成立以來基本未變,可見其威力。

邊緣服務是無狀態的,這意味著它們不能直接寫入集中式資料庫。這不僅有利於擴充套件系統,而且是一個非常好的安全功能。我們所有暴露在外部的系統都被禁止寫入中央資料庫,從而降低攻擊者破壞或竊取有價值資料的風險。通過在開發人員中根深蒂固的安全意識,我們可以通過設計獲得安全性,而不必回溯性地修補系統中的漏洞。

 

分散式資料庫

最近,我們面臨著使我們的支付 API 具有冪等性的挑戰。這意味著如果商家向我們傳送兩次完全相同的付款,我們應該只處理一次,但在兩種情況下都返回相同的響應。

正如您現在所知,我們不想通過將某些商家的付款限制在某些機器上來實現這一目標,因為這意味著這些機器不再具有線性可擴充套件性。這些資訊需要在本地可用,因此我們最終決定將分散式資料庫Cockroach與我們的 PAL整合。

我們可以在這裡自己構建一些東西(可能在 PostgreSQL 之上),但這實際上不是我們的核心業務,並且有幾個開源選項滿足我們的標準。然而,正確瞭解資料庫並將其優化到我們對它感到滿意的程度需要付出大量的努力。有關在開源和自行構建之間做出決定的另一個示例,請參閱有關我們的圖風險引擎的部落格

 

未來的迭代

我們邊緣服務的下一個重要步驟是動態擴充套件它們。我們在全球多個資料中心管理自己的基礎設施,並提供裸機,但硬體和軟體仍然緊密耦合。

我們不部署到雲的原因部分是歷史原因,部分是法律原因,部分是技術原因。在某種程度上,因為我們現在需要動態擴充套件,我們正朝著在內部雲上執行我們的系統邁進。關於容器化工作的部落格即將釋出。

作者:Adyen 技術主管 Willem Pino

 

相關文章