1. 程式人生 > >MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

大家好!我是網易資料運維工程師杜明友,大家可以叫我老杜。首先介紹一下網易雲,是網易集團旗下雲端計算和大資料品牌,本文要深入分析的案例是網易雲旗下的即時通訊雲平臺業務,開發者通過整合客戶端SDK和雲端OPEN API,即可快速實現強大的IM功能,作為PaaS服務模式的網易雲信全面支援Android、iOS、Web、PC等多平臺。還提供了高階通訊功能,包括實時音視訊、互動直播、教學白板、專線電話、簡訊、專屬雲在內的獨家功能以及更多其他服務。網易雲信滿足包括遊戲、協同辦公、線上醫療、線上客服、線上教育、娛樂、諮詢、生活服務、物流、旅遊、金融等各行業各種產品的即時通訊服務需求。客戶案例有順豐、寶寶樹、挖財網、網易雲音樂、網易雲課堂等等。分散式資料庫架構介紹  

作為時下最火爆的IM雲服務,網易雲無時不刻不在為百萬商家億級終端使用者提供便捷的即時通訊服務。商家產品爆款、使用者活躍交流都在考驗著我們的業務系統。如何保障系統的穩定執行,支撐更大的併發,提供真正的可擴充套件的IM雲服務一直是我們非常關注的一個問題。

作為網際網路的一支老牌勁旅,我們在大併發海量網際網路系統構建方面也有著非常深厚的積累與經驗。在資料庫選擇上我們使用了網易私有云中的分散式資料庫服務(雲DDB)

其架構圖如下

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

雲DDB主要包括五個元件: NLB、SQL Proxy、DBN、Master、SYSDB

  1. NLB是負載均衡服務,基於LVS打造,負責將應用請求轉發到後端SQL Proxy, 同時定時檢測後端SQL Proxy的可用性,及時將故障機器從叢集中摘除。
  2. SQL Proxy實現了MySQL協議,接收客戶端請求,同時負責將請求路由到具體的後端資料庫節點,並返回資料給客戶端。如果資料請求分佈在多個節點,則可能使用2PC協議進行分散式事務(保障資料一致性)。
  3. DBN則是底層真正負責資料存取的服務,通常是一個關係型資料庫,目前支援MySQL、Oracle。
  4. Master是管理服務,負責管理叢集,比如新建表、設定資料路由策略、設定客戶端連線池引數、DBN切換、配置變更通知等,操作結果(叢集元資料)將持久化到SYSDB。
  5. SYSDB是一個數據庫,負責儲存分散式資料庫的元資料資訊,包括表、欄位、許可權、資料路由等資訊

DBN與SYSDB使用的是網易私有云RDS,其它元件則部署在使用雲主機上,雲DDB服務的核心元件SQL Proxy以及DBN都是可擴充套件的,並且高可用的。

DDB處理邏輯簡單來說就是應用請求通過NLB轉發到具體SQL Proxy上,SQL Proxy解析SQL生成執行計劃,下發請求至底層節點,收到DBN資料後做一定的處理返回給客戶端。

高可用分散式DB服務構建指南  

網易IM雲服務目標是支援彈性擴充套件、訊息必達,那就需要在保證高吞吐、高效能的同時,那就需要資料的高可用性:簡單而言就是資料儲存服務要高可用並且資料不丟失。

因為關係型資料庫發展幾十年在穩定性方面對比其他資料儲存方案來說存在非常大的優勢,基於此,業務很多對資料一致性的場景都是直接依賴於DB。

比如為了保證訊息準確到達,傳送方的訊息需要先持久化到DB,再發送到接收方,接收方收到之後更新為已接收狀態,因此對資料庫是重度依賴。

對關係型資料庫來說高效能高可用跟資料不丟失又往往是魚跟熊掌的關係,要保證資料完全不丟失的話,資料必然是要同時寫入到主庫與從庫才算完成,此時如果從機異常,資料寫入將失敗,這將導致資料庫服務不可用,相信很少有人能接受。

所以通常在資料一致性與服務可用性上會做一定的妥協,即正常情況下表現為主從強一致性模式,異常情況下則退化為非同步模式。這在MySQL裡面我們稱之為Semi sync複製,Oracle 複製(DataGuard) 裡面則為最大保護模式。

在保證資料服務高性高吞吐的情況下儘量避免資料丟失,我們對網易雲DDB底層DBN做了如下設定:

  1. 將sync_binlog與innodb_flush_log_at_trx_commit同時設定為1,每次資料庫寫操作都會持久化binlog與redo log到磁碟上,保證資料的永續性。
  2. 開啟VSR(virtual sync replication),保證主從能實時一致。
  3. 開啟Group Commit,以及從庫的並行複製,提升主從效能。

第2點裡的VSR,這個是網易MySQL分支InnoSQL的一個特性,InnoSQL在官方半同步複製(semi sync)基礎上做了部分改進,改善了主庫宕機時主從資料不一致問題,實現機制如圖所示:

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

簡單來說,MySQL5.5版本中官方semi sync是在binlog與redo都寫完後再將binlog傳輸到從庫,而vsr則是在binlog寫完後與redo log寫之前傳輸binlog,這樣做的好處是可以避免事務日誌提交後主庫宕機恢復後資料幻讀問題。(在官方MySQL5.7中這個問題得到解決,見rpl_semi_sync_master_wait_point引數解釋)

當然這樣做也有缺點,事務需要等待資料傳輸到從庫後再返還,肯定會增加一定的延遲時間,針對這個問題,優化方法就是第三點開啟group commit。開啟後多個事務的binlog一次性提交到磁碟跟傳輸至從庫,這樣可以減少磁碟fsync次數並提升吞吐量。

以下是sync_group (vsr+group commit) 與原生semi sync、 sync(vsr) 、async(不開啟semi sync) 之間效能對比圖,可以看到 vsr + group commit效能與非同步複製幾無差別:

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

同時為了從庫及時同步資料,我們在從庫上開啟並行複製,主庫上事務並行提交從庫上也可以並行恢復,這樣大併發寫入下從庫沒有基本延時。

隨著業務的暴漲,資料量規模及QPS也暴漲幾百倍,經過多次擴容後,為了提升DDB效能及容量,我們將IM雲底層DBN節點從RDS遷移到物理機,並且使用大量的SSD作為底層儲存。遷出RDS後DDB底層節點便不再擁有高可用這一特性,為此我們自己開發了一套DDB底層節點監控與切換工具DDB Monitor,此時DB高可用架構圖變成

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

DDB Monitor可用於執行日常資料庫擴容切換、故障切換、狀態監控等工作

故障切換模式下會定時(幾秒) 做如下事情:

  1. 狀態檢測,包括檢測DBN存活狀態,主從複製關係,binlog位置點,semi狀態等
  2. 模擬資料寫入,檢查主庫是否可寫

在判斷MySQL主從何時可以切換方面,與其它開源工具可能有些不同,需要滿足以下情況才可能觸發故障切換:

  1. DBN主節點無法連線,錯誤號為2000-3000間指定幾個(避免max connection等服務端反回的錯誤號造成誤判)
  2. DBN主節點指定時間內重試多次仍無法寫入
  3. 從庫接收到的binlog已經應用完成或者在若干秒時間內應用完成
  4. 上一次資料庫vsr(semi sync)狀態正常或上一次從庫收到的binglog落後主庫若干位元組內 (根據業務資料重要程度設定)
  5. 如果主庫無法連線,從庫show slave status中Slave_IO_Running狀態需為NO (從庫與DDB Monitor工具同時監控主庫是否宕機,避免腦裂問題)
  6. 從庫Slave_SQL_Running狀態需為 Yes

其中條件1與條件2 需要滿足至少1者。 4中表示如果對主從一致性要求很高需要滿足上次檢測vsr(semi sync)正常才能切換,而如果可以容忍一定的資料丟失那麼可以設定檢測上次主從同步binlog差值在指定範圍內即可切換。

故障切換後,SQL Proxy收到Master訊息會重新建立到正確DBN的連線,主庫宕機情況下基本可以在秒級別完成切換。

當然除了上面這些說的這些部署上保障高可用外之外,加強資料庫設計與監控也是保障資料庫穩定執行非常重要的一環。

資料庫設計方面的措施主要有:

  1. 按照資料庫設計規範進行表、SQL設計。表設計儘量精簡,從資料訪問角度設計表結構,在正規化與反正規化間要做合理的取捨
  2. 資料請求儘量精簡快,並減少垮節點訪問,提升資料庫真正的服務時間
  3. 高頻查詢需要新增快取,使用者配置、群資訊配置等少更新高訪問請求走要快取
  4. 對資料一致性要求不高以及資料分析統計類的請求放到從庫查詢
  5. 非核心功能、核心但數量少頻次低模組走RDS,避免相互影響
  6. 與應用合作,新增對DB衝擊較大業務場景(比如聊天室)提供限流支援

資料庫監控方面我們主要做了如下以下幾個方面:

  1. DDB各個元件的網路、系統層面通用性指標監控
  2. SQL Proxy、DDB Master jvmgc資訊、連線數、cpu、請求量、響應時間記憶體使用率日誌等監控
  3. DBN節點(MySQL) Global status、processlist、innodb engine status、slowlog、資料增長率、表分割槽、檔案控制代碼等監控
  4. 資料運維平臺上報表展示基於海量監控資料下通過一定演算法得到資料庫容量、執行狀態、重要指標不同時間同比環比,風險點分析提示,風險SQL指示等

一套DDB內通常包含幾百個維度的指標監控及幾十個維度的報警項

多機房高可用實踐  

在過往的運維經歷中,我們遇到過機櫃掉電、機房大面積故障等事情,這種情況的發生會嚴重影響產品可用性。所以對於雲信等重要產品,單機房高可用顯然無法滿足業務追求

多機房是個非常複雜的工程,不僅需要在部署上有多機房部署,在應用層面也需要支援多機房架構,雖然我們在產品發展初期就開始了多機房高可用建設,但到目前我們並沒有完全做到自動化故障切換

這裡介紹下我們做的工作也是拍磚引玉,希望大家提出寶貴意見

我們多機房高可用主要做到的工作

  1. 備機房距主機房至少需隔兩百公里距離,機房間必須有專線
  2. 服務入口多機房,客戶端請求根據流量配置轉發到不同機房伺服器
  3. 應用與依賴元件多機房高可用部署(MQ、Hbase、物件儲存服務等),部分元件需要應用雙寫多機房,比如Hbase、物件儲存的寫入等
  4. 應用訪問資料服務通過配置管理服務(DISCONF)獲取,資料庫與快取通過使用功能(MySQL)或複製工具(快取) 做跨機房資料複製
  5. 監控多機房元件的可用性,PE與DBA部署好自動化切換工具
  6. 確定基於binlog與應用日誌的重要資料校驗與補償機制

最後資料庫高可用架構圖:

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

人工切換始終會存在一定的延時,不過我們運維部強大的運維協作工具Stone支援移動端執行伺服器命令,可以隨時隨地執行切換操作:

MySQL分散式資料庫高可用實踐:架構、複製機制、多機房

以上就是我此次分享的全部內容,感謝大家的參與,謝謝大家

QA環節

Q1:有什麼好的方案能在保證業務不中斷的情況下實現跨機房大資料庫遷移,在這過程中又如何保證資料的實時性呢?

A1: 資料庫的實時性 可以有專線網路 + DB複製 來保障, 不終端服務實現跨機房的話 就需要系統相關的所有元件都支援跨機房高可用,並且需要實現自動化切換。補充一點, 跨機房服務部終端,會犧牲一定的資料一致性。我:

Q2:請問你們都有哪些自己研發的模組開源呢?很想學習下

A2:網易InnoSQL是開源的,另外redis複製遷移工具 redis-migration也是開源的

Q3:關係型資料庫MySQL很流行,但是也有不足,我們最近在考慮有沒有替換的方案。能否將它和其他的對比一下?你們是怎樣做的選擇?

A3:首先我覺得最好是選擇你最熟悉的,能搞定的資料庫。GitLab資料丟失事故 我認為很大的原因是因為他們的工程師對postgresql 不是很懂。 另外MySQL發展其實非常快的,5.7 有很多非常好的特性,很多東西都借鑑了Oracle。

Q4:你們有什麼開源的跨機房資料實時同步工具嗎。

A4:我們網易內部有一套自己開發的資料複製工具DTS, 目前還沒有開源, 快取複製工具有開源 是 redis-migration。git 上大家可以搜一下

Q5:你們的資料訪問高峰是什麼時候呢?還是說一直比較平緩?還有,有沒有大規模遷移資料庫的經歷,可以講一講嗎?

A5:業務肯定有高峰低估的,一般晚上黃金時段是高峰期,凌晨是低谷。資料遷移的話其實做好工具後,資料大小量沒有太大的差別,資料量大的話 需要做限流。

Q6:從技術上選擇MySQL和PG有什麼區別?選擇他們的時候你們是選了最熟悉的還是做了技術選型的調研?

A6:我們選擇了最熟悉並且最適合我們的。PG跟MySQL都非常優秀,效能上也差不多。

Q7:能不能講講上次大規模故障的事情?多長時間內完成恢復?有哪些措施?資料如何備份?

A7: 故障恢復通常需要做好預案, 比如當你無法做到自動化切換的時候,就需要有一套切換的指令碼,另外故障切換後通常需要做好一定的限流,不能切完再掛。 資料備份方面:我們一套資料庫備份系統, 資料庫的備份會備份到儲存服務上

Q8:你們的採用分散式資料庫與單節點資料庫能完全相容嗎?

A8:大部分都能相容,少數極端的case不相容

Q9:你們線上業務單表資料量能去到多少?是如何對這些表進行優化?

A9:一般我們都會分表, 一張大表可能有幾十到幾百張字表,百億級表很多的,比如我們的訊息表。 表優化: 1 將歷史資料遷移到離線資料庫 2 精確好欄位長度 3 儘量以primary key 或者聯合索引去訪問表

Q10:為什麼不在sql proxy層使用mycat?最近使用了mycat感覺還不錯

A10:SQL Proxy跟我們DDB各元件是整合在一起的, DDB是2006年開始研發的,比市面上任何一款分庫分表工具都悠久,我們對比過SQL Proxy跟mycat,  各有優缺點。