架構師之路-分散式鎖

架構師之路-分散式鎖

4 人贊了文章

無論是12306、淘寶、還是京東,這些大型網站為了承受高並發的用戶訪問,必會使用分散式架構,而這種架構給系統的數據處理也帶來了一些問題。假設,現在系統里只有一張票了,用戶A和用戶B同時讀取到了這張票,並且同時下單。此時,你說這張票是A的還是B的呢?很明顯,要麼是A的,要麼是B的,一張票不可能同時分配給兩個人。但是如果不做其他處理,在這個場景中,用戶A和用戶B都可以下單成功,這下就亂了套了。

為了解決這個問題,現在比較常用的方案就是使用分散式鎖。通常我們使用較多的分散式鎖有兩類:基於RDBMS的分散式鎖和基於NoSQL的分散式鎖。

首先,基於RDBMS的分散式鎖。以MySQL為例,實現這種鎖的方式有兩種:

1、假設每張票都有一個唯一的ID(簡稱:票ID)。我們新建一張臨時表(欄位有:流水號、用戶ID、票ID、時間)。用戶下單是先在這個臨時表中寫入一條包含票ID的記錄,只有先寫的才能寫成功,後寫的會報錯。寫成功之後,就可以繼續下單,否則返回「下單失敗」。後續,如果用戶將票退掉,就需要將臨時表中的記錄刪除,以釋放該票。

2、在下單的表中,增加一個欄位version。下單前先獲取這個version值,下單的時候再將version的值作為一個過濾條件,只有當資料庫中的version和剛剛查詢到的version值一樣時,才可以下單。下單之後,需要將version的值加1。

3、在下單的時候,直接用select...for update語句,鎖定該記錄。其他用戶將無法再更新這條記錄。

其次,基於NoSQL的分散式鎖。這種鎖的實現更加簡單,它是利用的NoSQL的原子性操作實現鎖的功能。例如使用Memcached的add操作,只有當key不存在的時候才能操作成功,這樣就以為著當前線程到了鎖;另外通過delete操作釋放掉鎖。再比如Redis的setnx操作同樣是原子性操作,原理和Memcached的add操作一樣;不過為了釋放鎖,需要使用redis的expire命令(另外set命令包含了setnx和expire的功能,所以我們可以直接使用set命令)。

最後,基於Zookeeper的分散式鎖。這種鎖實現比較複雜一點,在我們的環境下還未使用過。以後補充。

通過上面兩類分散式鎖的理解,我們知道,分散式鎖就是讓系統在處理過程中找到一個單一點,在這個點上是遵循先到先得原則的,知道滿足這樣特點就可以用來實現鎖。不過很名下實現這個鎖之後,系統的性能必然會有所下降,其中的利弊需要系統根據實際情況來權衡。


推薦閱讀:

綠城關鍵時刻:內部架構大調整 輕重並舉啟動高周轉
58架構師解讀:如何優化秒殺業務的架構?
架構的一些思考From FunData
分散式架構與微服務架構——成為高級架構師,你想要的都在這裡
談談.NET架構師面試及如何設計面試題

TAG:架構 | 架構師 | 分散式系統 |