摘要:目前市面上已經(jīng)有OneProxy、TDSQL、MyCat、360Atlas等出色的數(shù)據(jù)庫中間件,對于如何選型,不同公司會有不同的考慮,當(dāng)然也有公司會選擇自研,網(wǎng)易電商樂得在實(shí)際生產(chǎn)中就根據(jù)需要研發(fā)了自己的中間件Cetus,并于不久前開源。...
電商系統(tǒng)中,隨著業(yè)務(wù)量的增大,讀寫 QPS 越來越高,單節(jié)點(diǎn) MySQL 實(shí)例壓力越來越大,單純的對服務(wù)器硬件升級已經(jīng)無法滿足生產(chǎn)環(huán)境的需要,對數(shù)據(jù)分片增加多個(gè)節(jié)點(diǎn),降低單節(jié)點(diǎn) MySQL 實(shí)例的壓力成了必然選擇。傳統(tǒng)的分片是通過 DAO 層進(jìn)行的,但是 DAO 層對數(shù)據(jù)分片存在諸多問題:
從業(yè)務(wù)角度看,配置修改需要重啟服務(wù),代價(jià)巨大;需要對分片結(jié)果集進(jìn)行處理,業(yè)務(wù)邏輯愈加復(fù)雜;功能相對簡單。
從數(shù)據(jù)庫運(yùn)維角度看,配置管理的統(tǒng)一化難度較大;DB的升級、遷移等操作復(fù)雜。
因此 MySQL 數(shù)據(jù)庫中間件應(yīng)運(yùn)而生,解決了上述 DAO 層的諸多問題。MySQL 數(shù)據(jù)庫中間件為業(yè)務(wù)提供了統(tǒng)一的入口、對業(yè)務(wù)透明,提供了讀寫分離、分片、豐富的路由策略,以及其它較為實(shí)用的統(tǒng)計(jì)、管理、鑒權(quán)等功能。
目前市面上已經(jīng)有 OneProxy、TDSQL、MyCat、360 Atlas 等出色的數(shù)據(jù)庫中間件,對于如何選型,不同公司會有不同的考慮,當(dāng)然也有公司會選擇自研,網(wǎng)易電商樂得在實(shí)際生產(chǎn)中就根據(jù)需要研發(fā)了自己的中間件 Cetus,并于不久前開源。
項(xiàng)目地址:
GitHub
碼云
Cetus 主打穩(wěn)定、高性能和對開發(fā)友好,并以 OneProxy 等出色中間件為追趕目標(biāo),那它的具體設(shè)計(jì)思路與能力如何?開源中國采訪了 Cetus 負(fù)責(zé)人@王斌,請他從項(xiàng)目背景、設(shè)計(jì)思路、研發(fā)經(jīng)驗(yàn)與未來計(jì)劃等幾個(gè)方面為讀者全面解讀 Cetus。本文由采訪整理而成。
嘉賓介紹
王斌,網(wǎng)易高級技術(shù)專家,愛好開源,tcpcopy 和 Cetus 主要開發(fā)人員之一,希望為中國開源做點(diǎn)貢獻(xiàn),目前主要負(fù)責(zé) Cetus 項(xiàng)目,關(guān)注領(lǐng)域包括分布式數(shù)據(jù)庫、網(wǎng)絡(luò)與機(jī)器學(xué)習(xí)。
項(xiàng)目背景
樂得作為網(wǎng)易的電商系統(tǒng),近年來業(yè)務(wù)不斷發(fā)展,隨之而來的是數(shù)據(jù)庫數(shù)據(jù)量和訪問量的不斷變大。當(dāng)數(shù)據(jù)量達(dá)到一定量級,尤其是寫請求過于頻繁時(shí),傳統(tǒng) MySQL 架構(gòu)很難支持樂得的大業(yè)務(wù),因此我們考慮用水平切分的方式進(jìn)行優(yōu)化,以降低單個(gè)庫、單個(gè)表的壓力。
已有的開源分布式 MySQL 中間件具有不穩(wěn)定、對開發(fā)不友好等問題,很難直接采用,于是我們決定自主開發(fā)一款分布式事務(wù)功能的 MySQL 中間件,我們有幾個(gè)目標(biāo)想要達(dá)到,包括高可用、高性能、讀寫分離、分庫等。自己開發(fā)有個(gè)好處就是自研可控,可以按照實(shí)際需求添加新功能,并且可以及時(shí)修復(fù) bug。
這一次將 Cetus 開源也是想跟同行一起將它打造成一款出色的 MySQL 中間件,把 MySQL 后端集群整合成一個(gè)強(qiáng)有力的分布式數(shù)據(jù)庫。
讓 MySQL 更加強(qiáng)大
先介紹一下 Cetus 這個(gè)名字的意思,Cetus 這個(gè)英文翻譯成中文是“鯨魚座”,大家知道 MySQL 官方 logo 是海豚,鯨魚和海豚同屬于一個(gè)類別,而鯨魚體型更大點(diǎn),把這個(gè)項(xiàng)目命名為 Cetus,一方面是想讓 MySQL 更加強(qiáng)大的意思,另一方面鯨魚座代表了我們有著胸懷宇宙的情懷,想把 Cetus 做得更好、更長久。
Cetus 專注于性能、穩(wěn)定和分布式事務(wù),目標(biāo)是做一款可以媲美 OneProxy 和 TDSQL 等商業(yè)軟件的中間件。
下邊拿 Cetus 和一些知名的數(shù)據(jù)庫中間件或者NewSQL一起做個(gè)小分析:
OneProxy 是商業(yè)軟件,在穩(wěn)定性和性能方面遠(yuǎn)勝其它開源中間件,它一直是我們追趕的對象。
TiDB 代表了 NewSQL,是為大數(shù)據(jù)設(shè)計(jì)的,但由于成本較高,在可以使用 MySQL 的地方不建議使用 TiDB。
TDSQL 是騰訊開發(fā)的數(shù)據(jù)庫中間件,為騰訊云服務(wù),它在 MySQL XA 分布式事務(wù)方面進(jìn)行了很多探索,為我們的分布式事務(wù)處理提供了很多思路。
MyCat 功能較為復(fù)雜,細(xì)節(jié)方面還待改善(如算法沒有優(yōu)化、存在很多使用上的坑),用戶的抱怨比較多,與優(yōu)秀的數(shù)據(jù)庫中間件差距較大。
至于360 Atlas,它是一個(gè)長期沒有更新的中間件,設(shè)計(jì)、穩(wěn)定和性能不佳,導(dǎo)致了很多用戶放棄使用。
……
了解到其它開源和商業(yè)數(shù)據(jù)庫中間件的設(shè)計(jì)思路和存在的問題,我們在 Cetus 中大量借鑒和改進(jìn),這成了 Cetus 的優(yōu)勢。相比其它開源數(shù)據(jù)庫中間件,Cetus 會更加貼近用戶,兼顧開發(fā)和整體效率,同時(shí)規(guī)避了影響數(shù)據(jù)庫中間件穩(wěn)定和性能的坑。主要特點(diǎn)有:
自主開發(fā)的解析器,無需依賴第三方解析器,更新可控
異步處理,無任何阻塞,類似 Nginx
并行處理,對多個(gè)后端并行訪問,減少延遲
tcp stream 處理,tcp stream 可以分解大響應(yīng)處理過程,從而可以公平處理各個(gè)外部事件,同時(shí)也解決了內(nèi)存炸裂問題
分布式事務(wù)支持
對開發(fā)無感知,開發(fā)無需去了解這個(gè)事務(wù)是不是分布式事務(wù),像MyCat、DRDS 等中間件需要用戶顯式去指定這個(gè)事務(wù)是不是分布式事務(wù),這對開發(fā)人員不是很友好
分布式事務(wù)深度優(yōu)化,繼承了騰訊 TDSQL 的不少優(yōu)良特點(diǎn)
緊跟 MySQL 趨勢
在重置 MySQL 連接方面,MySQL 5.7 開始支持 reset conn,而 Cetus 已經(jīng)采用了 reset conn 代替 change user,以降低 MySQL 的 CPU 開銷
支持 MySQL Group Replication,集群產(chǎn)生新的寫節(jié)點(diǎn),Cetus 會及時(shí)更新寫節(jié)點(diǎn)信息,實(shí)現(xiàn)服務(wù)高可用
利用GTID tracking,自動實(shí)現(xiàn)一致性讀(正在開發(fā)中)
設(shè)計(jì)思路與技術(shù)細(xì)節(jié)
Cetus 位于應(yīng)用程序與 MySQL 數(shù)據(jù)庫之間,作為前端應(yīng)用與數(shù)據(jù)庫的通訊。其中,前端應(yīng)用連接 LVS 節(jié)點(diǎn),LVS 節(jié)點(diǎn)映射端口到多個(gè) Cetus 服務(wù),后者通過自身的連接池連接到后端的數(shù)據(jù)庫。
整體網(wǎng)絡(luò)架構(gòu)如下圖所示:
Cetus 主要的功能模塊包括以下五個(gè)部分:
讀寫分離
分庫
SQL 解析
連接池
管理功能
各個(gè)功能模塊間的交互關(guān)系如下:
其中,SQL 解析模塊為后續(xù)讀寫分離和數(shù)據(jù)分片等功能解析出 SQL 類型、表名和查詢條件等關(guān)鍵信息;連接池模塊是自維護(hù)連接池,支持 Cetus 根據(jù)需求查詢和檢測后端,維護(hù)連接數(shù),具有高效連接共享性、事務(wù)與 Prepare 的前后端綁定功能和熱點(diǎn)連接重用與連接等待機(jī)制;管理功能模塊通過用戶在管理界面輸入,獨(dú)立認(rèn)證并轉(zhuǎn)到下一狀態(tài),給用戶回復(fù)狀態(tài)查詢結(jié)果或調(diào)整參數(shù)。
Cetus 的整體工作流程:
Cetus 讀取啟動配置文件和其他配置并啟動,監(jiān)聽客戶端請求;
收到客戶端新建連接請求后,Cetus 經(jīng)過用戶鑒權(quán)和連接池判斷連接數(shù)是否達(dá)到上限,確定是否新建連接;
連接建立和認(rèn)證通過后,Cetus 接收客戶端發(fā)送來的 SQL 語句,并進(jìn)行詞法和語義分析,對 SQL 語句進(jìn)行解析,分析 SQL 的請求類型,必要時(shí)改寫 SQL,然后選取相應(yīng)的 DB 并轉(zhuǎn)發(fā);
等待后端處理查詢,接收處理查詢結(jié)果集,進(jìn)行合并和修改,然后轉(zhuǎn)發(fā)給客戶端;
如收到客戶端關(guān)閉連接的請求,Cetus 判斷是否需要關(guān)閉后端連接,關(guān)閉連接。
如下圖所示:
Cetus 目前分為兩個(gè)版本,分別是讀寫分離和分庫版本,這主要有兩個(gè)考慮:
分庫解析器和讀寫分離解析器很不一樣
Cetus 是基于 MySQL proxy 基礎(chǔ)上做的,由于原先代碼架構(gòu)不是很好,不易統(tǒng)一,隨著以后代碼架構(gòu)的不斷完善,兩個(gè)版本統(tǒng)一問題會最終得到解決
在讀寫分離版本中,通過對 SQL 進(jìn)行解析,根據(jù) SQL 特點(diǎn)和 GTID tracking 智能選擇路由主庫或從庫,從而實(shí)現(xiàn)讀寫分離,減少主庫的壓力,同時(shí)通過相關(guān)策略,保證從庫上進(jìn)行負(fù)載均衡。
而分庫的思想是參考了 Fabric 和 OneProxy,采用了 vdb 的思想,一個(gè) vdb 代表一個(gè)具體的分片規(guī)則,Cetus 確保同一個(gè) vdb 內(nèi)可以 join,不同 vdb 相互隔離,兼顧垂直拆分和開發(fā)對 join 的需求,不同 vdb 之間可以走分布式事務(wù)。
但 Cetus 基于以下考慮,不支持分表:
MySQL 分區(qū)性能會越來越好
Oracle 分區(qū)功能強(qiáng)大,而 MySQL 是 Oracle 公司的,并且 MySQL 5.7 以后的分區(qū)性能越來越好。
我們電商系統(tǒng)沒有用到分表功能
我們預(yù)測,未來 MySQL 分區(qū)會逐漸取代分表,類似 Oracle 原先走的路線,鑒于這個(gè)判斷和緊跟 MySQL 趨勢,樂得電商放棄了分表功能開發(fā)。
研發(fā)過程中暴露的問題
在項(xiàng)目開發(fā)過程中,我們遇到了一些難點(diǎn)與坑,并且有相應(yīng)的解決思路,這里與大家分享一下。
構(gòu)造分庫測試環(huán)境
我們改造了 tpcc、Zabbix 等軟件,以支持分布式數(shù)據(jù)庫使用場景。改造 tpcc 是為了測試分庫性能和分布式事務(wù)性能;改造 Zabbix,是為了讓分庫版本盡快用起來,盡早去發(fā)現(xiàn)問題。
線上規(guī)避問題
線上如果出大的問題,開發(fā)是很難接受的,因此確保線上盡量不出大問題,是遇到的最大挑戰(zhàn)。為了更好地解決此問題,我們專門優(yōu)化了 tcpcopy,使其更加適合流量測試。
目前80%以上的線上潛在問題都被流量測試所發(fā)現(xiàn)。
分布式事務(wù)
MySQL 在這方面是不太完美的,一旦 MySQL 在分布式事務(wù)支持方面出問題,是需要去補(bǔ)救的。
在測試過程中,我們發(fā)現(xiàn) MySQL 在分布式事務(wù)處理方面有如下兩大問題:
1、只有主庫存在懸掛事務(wù)
MySQL 主庫已接受到 xa commit 通知,xa commit 未完成前,kill -9 殺掉 MySQL 主庫,再啟動 MySQL 主庫,主庫出現(xiàn)懸掛事務(wù),而從庫該分布式事務(wù)已提交。主庫此時(shí)需要執(zhí)行 xa commit 語句,提交分布式事務(wù),這個(gè)操作同步到從庫后,會導(dǎo)致從庫 SQL 應(yīng)用進(jìn)程報(bào)錯(cuò),提示找不到該分布式事務(wù)。
2、只有從庫出現(xiàn)懸掛事務(wù)
Cetus 向后端分片發(fā)送 xa prepare,分片 MySQL 主庫接收到 xa prepare,xa prepare 未完成前,kill -9 殺掉 MySQL 主庫,再啟動 MySQL 主庫,xa 事務(wù)已回滾,主庫未出現(xiàn)懸掛事務(wù);從庫出現(xiàn)懸掛事務(wù)。這種情況下,從庫需要回滾 xa 事務(wù),才能保證數(shù)據(jù)的一致性。
以上兩種情況,主庫的 xa 事務(wù)狀態(tài),跟 binlog 記錄的事務(wù)狀態(tài)不一致。在 MySQL 官方文檔找到解釋,MySQL 異常關(guān)閉,有可能導(dǎo)致數(shù)據(jù)庫狀態(tài)和 binlog 不一致。這些 bug,在非正常關(guān)閉 MySQL 時(shí)才出現(xiàn),正常關(guān)閉 MySQL 不會出現(xiàn)這個(gè)問題。如果出現(xiàn) xa 事務(wù)懸掛,可以用 Cetus xa 懸掛處理工具自動處理。
tcp stream 改造
由于 MySQL 協(xié)議是有狀態(tài)的協(xié)議,Cetus 是純異步的,再加上 tcp stream,處理過程就變得異常復(fù)雜。我們采用的策略是讓線上運(yùn)行禁止 tcp stream 功能的 Cetus,而流量測試環(huán)境使用 tcp stream 的 Cetus,這樣就很容易去發(fā)現(xiàn) tcp stream 的很多問題。
網(wǎng)易樂得目前使用 Cetus 已經(jīng)一年多了,線上沒有遇到大的問題,而在測試的時(shí)候遇到了原先 MySQL proxy 帶過來的一個(gè)問題,因?yàn)樵O(shè)置 max-open-files 過小導(dǎo)致 CPU 100%,也正因?yàn)檫@個(gè)問題,使我們堅(jiān)決部署了 tcpcopy 流量測試環(huán)境。
展望
我們對 Cetus 的短期計(jì)劃是讓用戶大量用起來,并完成基于GTID tracking一致性讀的功能, 對MGR 的完善支持和擴(kuò)容工具的完善。
長期計(jì)劃是在不斷成長中,將 Cetus 打造成類似 OneProxy 的高性能數(shù)據(jù)庫中間件,支持多進(jìn)程、query cache、ssl與更好的安全過濾等,為MySQL保駕護(hù)航。