58同城資料庫架構學習

壹頁書發表於2015-11-29
上週六去聽upyun的技術分享.
其中非常受用的是沈劍老師分享的58同城資料庫架構.

58同城都是服務化架構.他們主要的架構如下.

他們每個構建,或者說服務,都是由兩個雙向同步的資料庫和一個redis快取組成.
一般來說,保障資料庫讀能力的高可用比較簡單,多搭建幾個Slave即可.但是M-S架構有同步延遲的問題.

但是保障資料庫寫能力的高可用,則比較複雜.
因為雙向複製問題很多.兩個Master的資料可能會相互覆蓋.
另外主鍵生成,也需要應用層使用UUID或者 全域性事務ID生成器這種東西
雖然使用步長的方式,也可以使用Auto_increment.但是DBA管理這麼多庫,誰能記著這麼多庫的Auto_increment步長的資訊呢?
以後萬一擴容(原始的DBA可能已經離職),可能會造成資料丟失的事故.所以這種東西,就別留在資料庫層坑自己了..


58同城保障讀寫高可用的方式,還是很巧的.
首先,他們的Service層,都是讀寫 主Master的資料庫,這樣讀寫都在一臺庫,自然沒有同步延遲的問題.
他們的讀擴充套件,並不透過MySQL Slave,而是透過Redis.
這樣就可以控制需要實時的資料,直接讀資料庫;非實時的資料,走Redis快取.

他們寫擴充套件,是透過一臺MySQL Standby資料庫實現.
Master和Standby資料庫是雙向複製的關係.但是平時,這個StandBy資料庫沒有任何的讀寫請求.
Master和Standby透過一個VIP對外提供服務.平時VIP指向Master.
一旦Master故障,則切換VIP到StandBy資料庫.這樣就實現了寫的高可用.

這個方案的缺點就是浪費了50%的計算資源.但是我覺得Standby資料庫處理一些讀請求,也是可以的.
他們不用的原因,也許和我們一樣.因為經過SQL調優之後,Master資料庫的資源使用率甚至不到10%.
Master尚且用不完,還琢磨StandBy,就沒有意義了.

擴容:
這個方案對擴容是非常友好的.
首先,停止雙向複製,這時候兩個庫的資料是一模一樣的.
然後,增加分庫策略(Hash,範圍,路由表)


最後,給每個Master,增加StandBy


這種擴容的方式,也比較簡單.停機的時間很短.但是隻能按照倍數擴容.
2臺擴4臺,4臺擴8臺,8臺就得擴成16臺.

如果4臺擴充套件為5臺,58同城使用服務層雙寫的方式,切換之前,校驗資料.但是我覺得這種方式侵入程式碼,對於我們這種公司,基本不現實.因為我們甚至沒有服務化...

另外,他們的快取一致性策略如下



他們第一步先使快取失效
他們怕先更新資料庫,然後再操作快取的時候,萬一失敗.則快取會有不一致的情況.
如果先使快取失效,出現異常是可以捕獲,進而做異常處理.(我覺得這點沒必要,如果Redis不能失效,就不讓使用者提交事務嗎?顯然也是不合理的)

第二步,修改資料庫並提交.

第三步,再次使快取失效
因為第一步和第二步之間的空隙,如果有讀請求,在redis層miss了,則會將舊資料從新讀入redis.所以資料庫提交之後,要重新使快取失效.
第一步在我看來,只是Redis是否正常的一個測試.忽略感覺也是可以接受的.

第四步,給每個快取一個固定的過期時間
這樣即使快取不一致,也可以限制在一個時間範圍內.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1849323/,如需轉載,請註明出處,否則將追究法律責任。

相關文章