接受”不完美“:分散式事務學習總結

来源:https://www.cnblogs.com/depsi/archive/2018/01/30/8380756.html
-Advertisement-
Play Games

作為一個前端專業的人來說,對於事務的理解,一直停留在“要麼都成功,要麼都不成功”的小白階段。既然自己將2018年定義為”深入理解“的一年,那麼就從深入理解事務開始吧。 ...


作為一個前端專業的人來說,對於事務的理解,一直停留在“要麼都成功,要麼都不成功”的小白階段。既然自己將2018年定義為”深入理解“的一年,那麼就從深入理解事務開始吧。

什麼是事務?

正如文章開頭所說的:事務是一系列的動作,這些動作必須全部完成,如果有一個失敗,那麼事務就會回滾到最開始的狀態,仿佛什麼都沒發生過一樣。在企業級應用的開發過程中,事務管理是必不可少的技術,用來確保數據的完整性和一致性。

事務有四個特性,也就是經常被提到的ACID:

  • 原子性(Atomicity):所謂的原子性就是說,在整個事務中的所有操作,要麼全部完成,要麼全部不做,沒有中間狀態。對於事務在執行中發生錯誤,所有的操作都會被回滾,整個事務就像從沒被執行過一樣。
  • 一致性(Consistency):事務的執行必須保證系統的一致性,就拿轉賬為例,A有500元,B有300元,如果在一個事務里A成功轉給B50元,那麼不管併發多少,不管發生什麼,只要事務執行成功了,那麼最後A賬戶一定是450元,B賬戶一定是350元。
  • 隔離性(Isolation):所謂的隔離性就是說,事務與事務之間不會互相影響,一個事務的中間狀態不會被其他事務感知。
  • 持久性(Durability):所謂的持久性,就是說一單事務完成了,那麼事務對數據所做的變更就完全保存在了資料庫中,即使發生停電,系統宕機也是如此。

上面我們說到的事務,也可以稱為是”本地事務“。目前許多框架,都能夠很方便的支持本地事務。比如Spring Boot,只需要在方法前加上”@Transaction“的註解,就可以愉快的使用事務了。

但是,事務到此未知就結束了嗎?不是的,隨著企業應用越來越複雜,應用的架構也從單體架構演變到了SOA,還有現在炙手可熱的微服務。這時候,又出現了分散式事務的概念。

分散式事務

分散式事務,簡單來說就是指對資料庫的處理操作分佈在不同的節點之上,而且操作的數據,分佈於不同的資料庫。分散式事務,需要保證不同資料庫的數據一致性。

分散式事務產生的原因

資料庫分庫分表

處於數據量或者數據隔離的考慮,實際開發中需要進行分庫分表。原來一個庫現在變成了多個庫,這時候要保證數據一致性,就要用到分散式事務。
非同步確保型

應用SOA化

所謂的SOA話,就是業務的服務化。比如原來單機支撐了整個電商網站,現在對整個網站進行拆解,分離出了訂單中心、用戶中心、庫存中心。對於訂單中心,有專門的資料庫存儲訂單信息,用戶中心也有專門的資料庫存儲用戶信息,庫存中心也會有專門的資料庫存儲庫存信息。這時候如果要同時對訂單和庫存進行操作,那麼就會涉及到訂單資料庫和庫存資料庫,為了保證數據一致性,就需要用到分散式事務。

CPA與BASE

說到分散式事務,就離不開CPA原則與BASE方案。

CPA

CPA指的是,在一個分散式系統中,一致性(C)、可用性(A)、分區容錯性(P),三者不可兼得。CPA是NoSQL資料庫的基石。

  • 一致性:在分散式系統中的所有數據備份,在同一時刻是否同樣的值。(等同於所有節點訪問同一份最新的數據副本)
  • 可用性:在集群中一部分節點故障後,集群整體是否還能響應客戶端的讀寫請求。(對數據更新具備高可用性)
  • 分區容錯性:以實際效果而言,分區相當於對通信的時限要求。系統如果不能在時限內達成數據一致性,就意味著發生了分區的情況,必須就當前操作在C和A之間做出選擇。

CAP理論就是說在分散式存儲系統中,最多只能實現上面的兩點。而由於當前的網路硬體肯定會出現延遲丟包等問題,所以分區容忍性是我們必須需要實現的。所以我們只能在一致性和可用性之間進行權衡,沒有NoSQL系統能同時保證這三點。

BASE

BASE就是為瞭解決關係資料庫強一致性引起的問題而引起的可用性降低而提出的解決方案。

BASE是下麵三個術語的縮寫:

  • 基本可用(Basically Available)
  • 軟狀態(Soft state)
  • 最終一致(Eventually consistent)

常見的分散式事務解決方案

兩階段提交

兩階段提交(Two Phase Commit, 2PC), 具有強一致性, 是CP系統的一種典型實現,常見的標準是XA,JTA等。例如Oracle的資料庫支持XA。

下麵是兩階段提交的示意圖:
非同步確保型
圖的上半是兩階段提交成功的演示, 下半是兩階段提交失敗的演示。

兩階段提交目前並不是主流的解決方案,其主要原因是:協調者需要等待所有參與者發出yes請求,或者一個參與者發出no請求後,才能執行提交或者終端操作。這會造成長時間鎖住多個資源,造成性能瓶頸。如果參與者有一個耗時長的操作, 性能損耗會更明顯;還有一個缺點,就是實現複雜,不利於系統的擴展。

TCC(Try-Confirm-Cancel)

TCC, 是基於補償型事務的AP系統的一種實現, 具有最終一致性。所謂的TCC編程模式,也是兩階段提交的一個變種。TCC提供了一個編程框架,將整個業務邏輯分為三塊:Try、Confirm和Cancel三個操作。以線上下單為例,Try階段會去扣庫存,Confirm階段則是去更新訂單狀態,如果更新訂單失敗,則進入Cancel階段,會去恢復庫存。總之,TCC就是通過代碼人為實現了兩階段提交,不同的業務場景所寫的代碼都不一樣,複雜度也不一樣,因此,這種模式並不能很好地被覆用。

非同步確保型

通過將一系列同步的事務操作變為基於消息執行的非同步操作, 避免了分散式事務中的同步阻塞操作的影響。基於消息執行就是基於消息中間件的兩階段提交,本質上是對消息中間件的一種特殊利用,它是將本地事務和發消息放在了一個分散式事務里,保證要麼本地操作成功成功並且對外發消息成功,要麼兩者都失敗,開源的RocketMQ就支持這一特性,具體原理如下:
非同步確保型

執行步驟如下:

  1. MQ發送方發送遠程事務消息到MQ Server;
  2. MQ Server給予響應, 表明事務消息已成功到達MQ Server.
  3. MQ發送方Commit本地事務.
  4. 若本地事務Commit成功, 則通知MQ Server允許對應事務消息被消費; 若本地事務失敗, 則通知MQ Server對應事務消息應被丟棄.
  5. 若MQ發送方超時未對MQ Server作出本地事務執行狀態的反饋, 那麼需要MQ Servfer向MQ發送方主動回查事務狀態, 以決定事務消息是否能被消費.
  6. 當得知本地事務執行成功時, MQ Server允許MQ訂閱方消費本條事務消息.

需要額外說明的一點, 就是事務消息投遞到MQ訂閱方後, 並不一定能夠成功執行. 需要MQ訂閱方主動給予消費反饋(ack)

  • 如果MQ訂閱方執行遠程事務成功, 則給予消費成功的ack, 那麼MQ Server可以安全將事務消息移除;
  • 如果執行失敗, MQ Server需要對消息重新投遞, 直至消費成功.
  • 根據業務邏輯的具體實現不同,還可能需要對消息中間件增加消息不重覆, 不亂序等其它要求.

此方案適用於執行周期較長,實時性要求不高的場景。

最大努力通知型

這是分散式事務中要求最低的一種, 也可以通過消息中間件實現, 與前面非同步確保型操作不同的一點是, 在消息由MQ Server投遞到消費者之後, 允許在達到最大重試次數之後正常結束事務.這種方案適用於交易結果消息的通知等

微服務的事務

最近兩年,微服務的呼聲越來越高,不可避免的,微服務也會面臨事務的困擾。

  • 首先,對於微服務架構來說,數據訪問變得更加複雜,這是因為數據都是微服務私有的,唯一可訪問的方式就是通過 API。這種打包數據訪問方式使得微服務之間松耦合,並且彼此之間獨立,更容易進行性能擴展。
  • 其次,不同的微服務經常使用不同的資料庫。應用會產生各種不同類型的數據,關係型資料庫並不一定是最佳選擇基於微服務的應用一般都使用 SQL 和 NoSQL 結合的模式。但是這些非關係型數據大多數並不支持 2PC。

總結

事務,尤其是分散式事務,是一個很大的話題,除了上述列出的幾種解決方案,根據不同的業務要求,還有許多其他的解決方案。按照控制力度,分散式事務分為部分控制和完全控制兩種:

  • 部分控制就是各種變種的兩階段提交,包括上面提到的非同步確保型、TCC模式
  • 完全控制就是完全實現兩階段提交。部分控制的好處是併發量和性能很好,缺點是數據一致性減弱了,完全控制則是犧牲了性能,保障了一致性。
    具體用哪種方式,最終還是取決於業務場景。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在做一個後臺管理系統,前端是用時下火熱的vue.js,後臺是基於springboot的。因為後臺系統沒有登錄功能,但是公司要求統一登錄,登錄認證統一使用.net項目組的認證系統。那就意味著做單點登錄咯,至於不知道什麼是單點登錄的同學,建議去找一下萬能的度娘。 剛接到這個需求的時候,老夫心裡便不屑 ...
  • 橋模式對於理解 開閉原則 與 組合聚合復用原則 很有幫助,同時也可以加深對於繼承的認識.這也是一個聽起來奇妙,用起來好像似曾相識,或者說早就不經意間就使用過的模式. 用意 將抽象與實現解耦,使二者可以獨立變化. 毫無疑問,用意概括的非常簡練,初次接觸這個模式的人很難參悟到其中的奧妙.軟體的模式要在一 ...
  • 1.餓漢式、不支持併發: 此模式只能運行在單線程下,且類在載入時就已經創建好了實例,不管需不需要用。 2.懶漢式、不支持併發: 此模式只能運行在單線程下,在調用獲取實例的方法時才創建實例。 3.懶漢式、支持併發、synchronized: 4.雙重檢查鎖 、volatile(常用): 5.靜態私有內 ...
  • 一、集中式日誌 日誌可分為系統日誌、應用日誌以及業務日誌,系統日誌給運維人員使用,應用日誌給研發人員使用,業務日誌給業務操作人員使用。我們這裡主要講解應用日誌,通過應用日誌來瞭解應用的信息和狀態,以及分析應用錯誤發生的原因等。 隨著系統的日益複雜,大數據時代的來臨,需要幾十甚至上百台的伺服器是常有的 ...
  • 因為項目需求,需要車輛品牌信息和車系信息,昨天用一天時間研究了jsoup爬取網站信息。項目是用maven+spring+springmvc+mybatis寫的。 jsoup開髮指南地址:http://www.open-open.com/jsoup/ 這個是需要爬取網站的地址 https://car. ...
  • Github: "https://github.com/nnngu" 項目源代碼: "https://github.com/nnngu/nguSeckill" 前端交互流程設計 對於一個系統,需要產品經理、前端工程師和後端工程師的參與,產品經理將用戶的需求做成一個開發文檔交給前端工程師和後端工程師, ...
  • 在面向對象編程的過程中,我們很容易通過繼承、多態來解決縱向擴展。 但是對於橫向的功能。面向對象的是無法解決的。所以AOP——面向切麵編程其實是面向對象編程思想的一個補充。過濾器和攔截器是AOP思想的具體實現,本文講解了在Spring boot下對過濾器和攔截器的使用。 ...
  • 工程報錯:java.lang.NoClassDefFoundError 名稱:類文件衝突 原因: 問題1,Windows 系統在某些時候不區分大小寫,比如Windows會認為Test.class 和test.class 是一個文件,無法區分。 問題2,在項目工程中有多個源碼包(source fold ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...