网易云IM云服务的稳定原来是这样实现的
你們都知道,我們網易云的IM云服務是賣得很火的。
人紅壓力大,為了能給百萬商家億級終端用戶提供便捷的即時通信服務,保證我們的業務系統能承受住各種大壓力的考驗,如何保障系統的穩定運行,支撐更大的并發,提供真正的可擴展的IM云服務是一個很重要的問題。
這個問題,網易云首席DBA、網易資深數據運維工程師在上周一次分享中是這樣說的:
●●●
分布式數據庫架構介紹
作為互聯網的一支老牌勁旅,我們在大并發海量互聯網系統構建方面也有著非常深厚的積累與經驗。在數據庫選擇上我們使用了網易私有云中的分布式數據庫服務(云DDB),其架構圖如下:
云DDB主要包括五個組件: NLB、SQL Proxy、DBN、Master、SYSDB。
??NLB是負載均衡服務,基于LVS打造,負責將應用請求轉發到后端SQL Proxy, 同時定時檢測后端SQL Proxy的可用性,及時將故障機器從集群中摘除。
SQL Proxy實現了MySQL協議,接收客戶端請求,同時負責將請求路由到具體的后端數據庫節點,并返回數據給客戶端。如果數據請求分布在多個節點,則可能使用2PC協議進行分布式事務(保障數據一致性)。
DBN則是底層真正負責數據存取的服務,通常是一個關系型數據庫,目前支持MySQL、Oracle。
?Master是管理服務,負責管理集群,比如新建表、設置數據路由策略、設置客戶端連接池參數、DBN切換、配置變更通知等,操作結果(集群元數據)將持久化到SYSDB。
?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做了如下設置:
將sync_binlog與innodb_flush_log_at_trx_commit同時設置為1,每次數據庫寫操作都會持久化binlog與redo log到磁盤上,保證數據的持久性。
開啟VSR(virtual sync replication),保證主從能實時一致。
開啟Group Commit,以及從庫的并行復制,提升主從性能。
第2點里的VSR,這個是網易MySQL分支InnoSQL的一個特性,InnoSQL在官方半同步復制(semi sync)基礎上做了部分改進,改善了主庫宕機時主從數據不一致問題,實現機制如圖所示:
簡單來說,MySQL5.5版本中官方semi sync是在binlog與redo都寫完后再將binlog傳輸到從庫,而vsr則是在binlog寫完后與redolog寫之前傳輸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性能與異步復制幾無差別:
同時為了從庫及時同步數據,我們在從庫上打開并行復制,主庫上事務并行提交從庫上也可以并行恢復,這樣大并發寫入下從庫沒有基本延時。
隨著業務的暴漲,數據量規模及QPS也暴漲幾百倍,經過多次擴容后,為了提升DDB性能及容量,我們將IM云底層DBN節點從RDS遷移到物理機,并且使用大量的SSD作為底層存儲。遷出RDS后DDB底層節點便不再擁有高可用這一特性,為此我們自己開發了一套DDB底層節點監控與切換工具DDB Monitor,此時DB高可用架構圖變成:
DDBMonitor可用于執行日常數據庫擴容切換、故障切換、狀態監控等工作。
故障切換模式下會定時(幾秒) 做如下事情:
?狀態檢測,包括檢測DBN存活狀態,主從復制關系,binlog位置點,semi狀態等;
?模擬數據寫入,檢查主庫是否可寫。
在判斷MySQL主從何時可以切換方面,與其它開源工具可能有些不同,需要滿足以下情況才可能觸發故障切換:
DBN主節點無法連接,錯誤號為2000-3000間指定幾個(避免maxconnection等服務端反回的錯誤號造成誤判);
DBN主節點指定時間內重試多次仍無法寫入;
從庫接收到的binlog已經應用完成或者在若干秒時間內應用完成;
上一次數據庫vsr(semi sync)狀態正常或上一次從庫收到的binglog落后主庫若干字節內 (根據業務數據重要程度設置);
如果主庫無法連接,從庫show slave status中Slave_IO_Running狀態需為NO (從庫與DDB Monitor工具同時監控主庫是否宕機,避免腦裂問題);
從庫Slave_SQL_Running狀態需為 Yes。
其中條件1與條件2需要滿足至少1者。 4中表示如果對主從一致性要求很高需要滿足上次檢測vsr(semi sync)正常才能切換,而如果可以容忍一定的數據丟失那么可以設置檢測上次主從同步binlog差值在指定范圍內即可切換。
故障切換后,SQL Proxy收到Master消息會重新建立到正確DBN的連接,主庫宕機情況下基本可以在秒級別完成切換。
當然除了上面這些說的這些部署上保障高可用外之外,加強數據庫設計與監控也是保障數據庫穩定運行非常重要的一環。
數據庫設計方面的措施主要有:
?按照數據庫設計規范進行表、SQL設計。表設計盡量精簡,從數據訪問角度設計表結構,在范式與反范式間要做合理的取舍;
?數據請求盡量精簡快,并減少跨節點訪問,提升數據庫真正的服務時間;
?高頻查詢需要添加緩存,用戶配置、群信息配置等少更新高訪問請求走要緩存;
對數據一致性要求不高以及數據分析統計類的請求放到從庫查詢;
非核心功能、核心但數量少頻次低模塊走RDS,避免相互影響;
與應用合作,添加對DB沖擊較大業務場景(比如聊天室)提供限流支持。
數據庫監控方面我們主要做了如下以下幾個方面:
?DDB各個組件的網絡、系統層面通用性指標監控;
SQL Proxy、DDB Master jvmgc信息、連接數、cpu、請求量、響應時間內存使用率日志等監控;
DBN節點(MySQL) Global status、processlist、innodb engine status、slowlog、數據增長率、表分區、文件句柄等監控;
數據運維平臺上報表展示基于海量監控數據下通過一定算法得到數據庫容量、運行狀態、重要指標不同時間同比環比,風險點分析提示,風險SQL指示等。
一套DDB內通常包含幾百個維度的指標監控及幾十個維度的報警項。
●●●
多機房高可用實踐
在過往的運維經歷中,我們遇到過機柜掉電、機房大面積故障等事情,這種情況的發生會嚴重影響產品可用性。所以對于云信等重要產品,單機房高可用顯然無法滿足業務追求
多機房是個非常復雜的工程,不僅需要在部署上有多機房部署,在應用層面也需要支持多機房架構,雖然我們在產品發展初期就開始了多機房高可用建設,但到目前我們并沒有完全做到自動化故障切換。
這里介紹下我們做的工作也是拍磚引玉,希望大家提出寶貴意見。
我們多機房高可用主要做到的工作:
備機房距主機房至少需隔兩百公里距離,機房間必須有專線;
服務入口多機房,客戶端請求根據流量配置轉發到不同機房服務器;
應用與依賴組件多機房高可用部署(MQ、Hbase、對象存儲服務等),部分組件需要應用雙寫多機房,比如Hbase、對象存儲的寫入等;
應用訪問數據服務通過配置管理服務(DISCONF)獲取,數據庫與緩存通過使用功能(MySQL)或復制工具(緩存) 做跨機房數據復制;
監控多機房組件的可用性,PE與DBA部署好自動化切換工具;
確定基于binlog與應用日志的重要數據校驗與補償機制。
最后數據庫高可用架構圖:
人工切換始終會存在一定的延時,不過我們運維部強大的運維協作工具Stone支持移動端執行服務器命令,可以隨時隨地執行切換操作:
●●●
QA環節
Q1:有什么好的方案能在保證業務不中斷的情況下實現跨機房大數據庫遷移,在這過程中又如何保證數據的實時性呢?
A1: 數據庫的實時性 可以有專線網絡 + DB復制 來保障, 不終端服務實現跨機房的話 就需要系統相關的所有組件都支持跨機房高可用,并且需要實現自動化切換。補充一點, 跨機房服務部終端,會犧牲一定的數據一致性。需要補充的是,跨機房的服務部終端,會犧牲一定的數據一致性。
Q2:請問你們都有哪些自己研發的模塊開源呢?很想學習下。
A2:網易InnoSQL是開源的,另外redis復制遷移工具 redis-migration也是開源的。
Q3:關系型數據庫MySQL很流行,但是也有不足,我們最近在考慮有沒有替換的方案。能否將它和其他的對比一下?你們是怎樣做的選擇?
A3:首先我覺得最好是選擇你最熟悉的,能搞定的數據庫。GitLab數據丟失事故 我認為很大的原因是因為他們的工程師對postgresql 不是很懂。另外MySQL發展其實非常快的,5.7 有很多非常好的特性,很多東西都借鑒了Oracle。
Q4:你們有什么開源的跨機房數據實時同步工具嗎。
A4:我們網易內部有一套自己開發的數據復制工具DTS,目前還沒有開源, 緩存復制工具有開源是 redis-migration,GitHub 上大家可以搜一下。
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, ?各有優缺點。
——【特別推薦】——
為什么你的工作經驗不值錢
總結
以上是生活随笔為你收集整理的网易云IM云服务的稳定原来是这样实现的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于假冒网站仿冒网易云信官网相关情况的声
- 下一篇: 今天网易云有大事发生?!