剛作後端大概10個月,從遊戲前端開發轉向後端,看似熟悉的編程語言,在不一樣的領域內實際上要考慮的事情也是全然不一樣的。前端
當咱們談論後端開發,天然而然聯想到,後端是服務於前端的,也是承載、服務於業務的一個重要組成部分。系統的穩定性,正確性以及可用性都是須要考慮的問題。數據庫
作後端,說簡單也簡單,說難也很難,簡單是由於你只須要對數據進行增刪查改,聚合統計就完事了,說難是由於一旦涉及到可用性,必然離不開分佈式,然而咱們知道,由分佈式而引出的一系列問題纔是最爲棘手的,更不用說系統安全、部署、監控等一些列的落地措施。編程
你須要確保多個系統的業務數據不混亂,在某些跨服務功能的調用鏈中保持一致性,當某一個服務調用失敗以後進行重試或者回滾。後端
重試須要你的服務具有冪等性,也就是說,當引入重試機制以後,你須要確保一個服務在同一個業務上下文中屢次調用而不會產生額外的影響,例如銀行轉帳,若是多扣幾回錢或者多加了幾回錢對於公司的業務以及信譽來講都是沒法接受的,解決這個問題的辦法須要引入相似流水號的關聯標識,在不一樣的服務裏面造成一個標識上下文。安全
當咱們的整個後端系統根據業務領域分割爲不一樣的服務獨立成型時,多個服務之間相互調用每每會由於網絡緣由而失敗。硬件損壞、宕機、天然災害等一些列不可抗力因素告訴咱們,任何事情都有可能失敗,當你的系統規模超過閾值以後,偶然將會轉變爲必然。咱們要的作的,不該該是想出一個萬全之策強力約束保證咱們的系統必定會成功,或者懷着僥倖的心理上線而後惶惶不安的等待系統出現問題。反而更應該思考一下,當系統出現問題以後,如何快速有效的修復失敗所帶來的影響。由於咱們知道,既然咱們沒法保證100%成功,那惟一的出路便想出一個補救措施來預防失敗,這每每會更使人更有安全感。網絡
在討論如何解決分佈式一致性以前,咱們更應該反過頭來看一下,什麼是事務,它在單機模式下是如何保證業務的原子性的。咱們每每將業務事務和數據庫的事務混爲一談,一般來講這是沒問題的,由於後端作的不就是數據的存儲麼。但當咱們把這兩個進行區分的時候,會發現大多數的時候,咱們所說的事務,僅僅是經過數據庫提供的ACID來實現的。當你要對數據庫的多個表進行操做的時候,打開一個事務,而且進行相應的更新,而後提交事務,此時要麼成功,要麼回滾撤銷變動,經過數據庫提供的ACID保證咱們的數據不會由於受到中斷的影響而產生混亂。架構
但若是咱們分佈式以後呢?每個業務子系統擁有本身的數據庫,你如何保證一個業務流程,在跨子系統調用時保證原子性呢?編程語言
若是咱們把但願繼續寄託於數據庫,多個業務子系統使用同一個數據庫,數據庫自己將會成爲瓶頸,這樣便失去了一開始設計分佈式系統的初衷。分佈式
若是某一個子系統失敗以後,形成了數據的不一致,此時,要麼回滾以前的操做,要麼就想辦法讓這個失敗的調用變爲成功。設計
A做爲業務發起者調用B和C,B成功,C失敗,A知道C失敗以後該怎麼作呢?是從新調用一次C仍是通知B回滾呢?若是通知B回滾的時候也失敗了呢?
答案每每是不統一的,每個業務領域都有根據自身狀況進行處理的方式。有不少分佈式事務協議可以解決些許問題,可是這每每會形成複雜度的提高,致使未來的維護以及拓展變得舉步維艱。
CAP定理相信你們都有了解,在任什麼時候候咱們要麼取CP要麼取AP,CP的問題在於複雜、可用性以及可維護性差,AP的問題在於必定的時間內,數據會存在不一致性。若是選擇CP,是時候考慮一下業務的分割是否合理,只有極少的狀況咱們才須要保證強一致性。
咱們須要一種更爲聰明的方法,一種機制來保證咱們的系統可以達成最終一致性,這纔是分佈式系統須要解決問題的根本之道,而且已經有不少模式方法來幫助咱們達成咱們想要的結果。
換一個角度來說,分佈式事務,自己就是一個僞命題,由於系統是脆弱的,有太多太多的因素會形成事情不可控。
咱們要作對的事情,讓系統可以根據業務需求變動逐步演進,造成一個良性循環,根據業務需求、目標領域來設計系統,合理的進行分割纔是王道。
若是你的系統自己不匹配業務領域,而又把不合理、生搬硬套的架構應用於它,就會出現各類各樣的問題,這些問題在某些時候甚至是不可能解決的。
在我看來,有關於解決分佈式事務的技術,無非是在爲糟糕的設計進行彌補,致使系統到最後臃腫不堪。那麼什麼是好的設計呢?簡單的來講,它應該符合你所處領域的業務知識,技術是不能解決全部問題的,由於只有當你的業務邏輯說得通,領域模型設計的清晰,巧妙以後,纔可以解決那些看似不可能解決的問題。
不要妄想用一套通用的模式去套每個項目需求,這樣永遠不會擺脫問題。
分佈式系統在絕大多數時候,反脆弱、最終一致性纔是咱們真正須要去解決的問題。
PS:你的系統究竟有多大才會致使最終一致性會被人爲的察覺出來?但咱們知道數據最終將會一致不是嗎?:)