海量儲存系列之六

2021-09-23 16:37:45 字數 3687 閱讀 2757

上次我們講到,單機事務個我們面臨的問題,下面我們來說一些我所知的解決的方法。

在我開始做**資料層的時候,被問得最多的無非也就是:如何做事務,如何做join.至今仍然如此,我一般都會簡單而明確的跟對方說:沒有高效的實現方法。

雖然沒有高效的實現,但實現還是有的。作為引子,我們先來介紹一下這種實現的方式。

我們仍然以上一次講到的bob和smith為例子來說明好了。

開始的時候。bob要給smith100塊,那麼實際上事務中要做的事情是

事務開始時查詢bob有多少錢。如果有足夠多的錢讓bob的賬戶 -100 ,然後給smith 的賬戶+100 。最後事務結束。

如果這個事情在單機,那麼事情可以使用鎖的方式加以解決。

但如果bob在一台機器,smith在另外一台機器,我們應該怎麼做呢?

第一種最常被人想起的方法,就是兩段提交協議。

兩段提交協議從原理上來說是非常簡單的一套協議。

prepare(bob-100) at 機器a->prepare (smith+100) at 機器b ->commit(bob) ->commit(smith)

事務結束。

兩段提交的核心,是在prepare的階段,會對所有該操作所影響的資料加鎖,這樣就可以阻止其他人(或機器)對他的訪問。題外話,問個問題: )如果這時有其他節點,用相反的方向,進行更新,也就是先更新smith,然後更新bob.會有可能發生什麼事情呢?

兩段提交協議是被我們在大部分場景下放棄的乙個模型,原因主要是因為

tm本身需要記錄事務進行的過程,log要保證安全和可信,效能非常低。

鎖的利用率和並行性較低。

網路開銷較大

可見性要求實際上就等於讓快的操作等慢的。

所以從效能角度來說,這類需求不多也不常見。

既然這樣的模型不行,有沒有其他模型可以使用呢?

有的。在事務的過程中,細心的讀者不難發現,實際上事務中並不需要這麼強的一致可見性。

bob是需要強一致的,因為他的操作仰賴於他有多少錢,如果他的錢不夠100,那麼是不能讓他的賬戶變為負數的。但smith卻不需要,smith不需要判斷他的賬戶有多少錢,只需要把錢加到他的賬戶裡,不少給他,到賬時間盡可能短就可以。

smith不需要chech賬戶的錢數,這個前提非常重要,這也是我們能使用最終一致性的關鍵因素。

下面,我們來看一下另外的選擇吧。

bob的賬號在機器a上,smith的賬號在機器b上。

首先,我們在機器a上做以下操作:

本地事務開始

讀取bob的賬戶

判斷是否有充足餘額

更新bob的賬號,將bob的錢減少100

將需要給smith加100塊這個操作,以事務的形式插入到同機(a)的一張log表中,並自動生成乙個唯一的transactionid。

事務關閉

然後,非同步的傳送乙個通知,給乙個消費者。

消費者接到通知後,從bob的機器上讀取到需要給smith+100這個操作,以及該操作所對應的transactionid。

然後,按照如下方法進行運作

檢視在去重表內是否有對應的transactionid.如果沒有,則

開啟本地事務

將smith的賬戶+100

將transactionid 插入去重表

事務結束

這樣,我們也可以完成乙個交易的核心流程了。在交易類過程中的大量事務操作,都是以這樣的方式完成的。

下面,我們針對上面的這個流程的一些抉擇的點進行一些**。

首先,是bob這個機器,這裡涉及第乙個抉擇點。

如果bob是個消費大戶,短時間內進行了大量購買,那麼可能會造成的問題是,bob所在的那個機器會成為熱點,如果在某個突發的情況下,某個賬戶突然成為熱點,那麼這些有狀態的資料很難快速的反應並加以處理,會造成事務數在某個單節點大量堆積。造成掛掉。

可能的解決方法是:

利用兩段提交協議來讓原來的」 將需要給smith加100塊這個操作,以事務的形式插入到同機(a)的一張log表中,並自動生成乙個唯一的transactionid」這步操作放在另外的一台機器上進行。

這樣做的的好處是,無論bob怎麼是熱點,都可以通過水平的加log機器的方式來防止這種熱點的產生。

壞處則有:

1方案複雜度高

2額外的網路開銷

3訊息基於網路傳送後,會可能得到三個可能的反饋:1. 成功 2. 失敗 3. 無反饋。最麻煩的就是這個無反饋,他可能成功,也可能失敗。所以是不確定的狀態,需要進行事務的兩邊進行第二次確認,來確保這個事務的參與方是否都做了該做的事情,如果有一方做了類似commit的操作,那麼另外的一方應該commit.如果兩方都沒做commit操作,那麼應該回滾。

讓bob的庫餘量更高,並按照訪問壓力進行資料的切分,按照熱度進行資料劃分,放棄原有的簡單取mod的策略。來相容這種不均勻特性。

其次,如果有80個系統都關注著smith加了100這個操作的log,要做對應的處理(比如一些人要針對這個加錢操作做個打款簡訊推送,有些要做個資料分析等等),那麼這裡就有另外乙個問題,這些系統對bob所在的庫的讀取就會讓該機器成為悲劇的存在。

所以,可以考慮的方式是,增加乙個佇列,使用,推,拉,或推拉結合的方式將smith加100這個操作加以分發。這樣就可以減輕主機的壓力。

壞處則是:

1方案進一步複雜

2如何保證log到資料分發伺服器之間的資料同步是安全的和準確的?

3如何保證分發伺服器的可靠和冗餘?

4如何保證寫入分發伺服器的資料的安全和可靠?

再次,smith這邊也有問題,為什麼要使用一張去重表呢?其實是因為,在傳送端,也就是佇列將資料傳送到目標機器後,也可能從目標機獲取到三種不同的反饋,一類是成功(這個佔了大多數)。一類是失敗。還有一類是。。。沒反饋。

當然,最麻煩的還是這個沒反饋的情況,沒人知道這時候到底對方是做成功了呢?還是沒做成功,為了保證最大的吞吐量,又不能其他人都不做事兒了,就等對方的反饋。所以這裡就有另外的權衡了。

一般的模型有兩類,一類是用分布式事務來完成。

一類是使用努力送達的模型,說叫努力送達,顧名思義,就是只有得到成功的反饋,才停止投遞,而其他時候則重複投遞訊息,直到對方反饋成功為止。

兩種模型比較,顯然應該追求速度而放棄方便性,於是我們主要來說說這個努力送達以後所帶來的影響。

影響一 : 會有重複的投遞,也就是說,這個訊息可能會投多次,這對於update set version=version+1 這類的操作來說,是個比較毀滅性的打擊。

影響二:如果需要重複投遞的訊息過多,會導致log分發的機器消耗大量資源來進行重複投遞。這會影響server的穩定性

影響三:如果大量堆積訊息,那麼會造成訊息的嚴重delay。smith發現自己在1個月後收到了bob的錢,你說他會不會去k咱一頓: ) .

最後,額外記的這兩次log其實在某些場景下也是可以省去的。

以上,就是我在嘗試還原**的訊息和事務系統時所能大概想到的一些非常需要權衡和注意的問題點。

小小總結一下,整個問題的核心其實是冪等,說白了就是要能夠理解資料基於網路的同步過程中,無反饋是乙個經常發生的現象,在這種現象中,重複投遞比傻傻等待要有效率的多。所以,重複作為乙個side affect也就被預設的存在於系統中,所有的工程師都需要認識到這個問題的客觀存在,並採取方法去解決之。

在基於網路的資料同步過程中,一致性是第乙個被放棄的。然後資料和訊息不會出現重複,是第二個被放棄指標。

使用這種模型,我們可以放棄原來快得等慢的的模式,讓整體的吞吐量和效能不會受制於鎖的限制,所以**和支付寶才能夠支援如此大的交易量。完成大量交易訂單。

本文**於"阿里中介軟體團隊播客",原文發表時間"

2011-12-19 "

海量儲存系列之十三

在上一章中,我們主要介紹了規則引擎中最重要的乙個部分,自動擴容,在今天的章節,我們主要還是介紹一下我們在 tddl中的工程實踐吧。首先從原理開始吧。規則引擎是什麼呢?對應在上述例子裡面,其實就是dbnum pk 3 這個規則。他的變化可能很多,比如對於一致性hash則變為乙個if else 的表示式...

海量儲存系列之五

在上一章節,我們一起瀏覽了如何進行單機事務操作。下面我們來看一下分布式場景中我們碰到的問題吧。需要說明的一點是,這裡涉及到的權衡點非常的多。就我短短的工作經驗裡面,也只是能夠簡單的涉獵一部分,因為在事務這個領域,目前大家都在嘗試提出各種各樣的不同的方法,而在taobao,我們目前也沒有完美的解決這個...

海量儲存系列之十二

目前,團隊blog和sina輕部落格的發布進度已經完全相同,後續會全部 時間隔了比較久了,因為最近在過年臨近,所以都在準備這方面的事情。這裡提前祝大家新年快樂。然後還是回到我們的正題兒吧 本章,我們主要來討論資料的管理和擴容中最重要的乙個部分,資料遷移。資料遷移是資料運維中最為重要的乙個部分,在前面...