mysqlda分布式MySQL數(shù)據(jù)庫中間件
1. 概述
1.1. 數(shù)據(jù)分布式切分方式
分布式架構(gòu)中最難解決的是數(shù)據(jù)分布式問題,大部分?jǐn)?shù)據(jù)庫中間件都以分庫分表作為切分方式,好處是通用,但也存在以下問題:
擴(kuò)容過程需要以切片為單位在庫間移動(dòng)數(shù)據(jù)。擴(kuò)容規(guī)模受到切片數(shù)量限制,如果業(yè)務(wù)發(fā)展增長規(guī)模大大超出初期預(yù)估會(huì)導(dǎo)致切片數(shù)量不夠用,陷入數(shù)據(jù)硬遷移的困境。
同一業(yè)務(wù)對(duì)象的數(shù)據(jù)分散在不同庫中,無法做聚合、連接等復(fù)雜處理。
跨庫意味著分布式事務(wù),雖然現(xiàn)在有兩階段提交等解決方案,但理論上并不總是那么可靠,尤其是在金融行業(yè)苛求數(shù)據(jù)強(qiáng)一致性時(shí)。
以核心業(yè)務(wù)對(duì)象切分方式則以產(chǎn)品線入口業(yè)務(wù)對(duì)象作為切分目標(biāo)(比如互聯(lián)網(wǎng)業(yè)務(wù)系統(tǒng)中的客戶對(duì)象),開戶交易途徑數(shù)據(jù)庫中間件,以手機(jī)號(hào)或其它入口字段作為核心字段做附帶權(quán)重的客群切分,歸屬到數(shù)據(jù)庫集群中的某個(gè)庫中,并保存分配結(jié)果,以后該客戶的所有交易都會(huì)被發(fā)往其歸屬庫處理。當(dāng)需要庫存儲(chǔ)擴(kuò)容時(shí),只需簡單的增加MySQL歸屬庫到數(shù)據(jù)庫集群中,在數(shù)據(jù)庫中間件系統(tǒng)中增加新歸屬庫配置信息,并調(diào)大新庫被分配權(quán)重,新客戶分配歸屬到新庫的概率變大,當(dāng)新庫存儲(chǔ)增長到一定程度時(shí)調(diào)平分配權(quán)重,新客戶分配歸屬到所有庫的概率均等,直到下一次擴(kuò)容。
以核心業(yè)務(wù)對(duì)象切分方式的好處是:
無需預(yù)估切片,其擴(kuò)容過程無需移動(dòng)任何數(shù)據(jù)。
由于同一業(yè)務(wù)對(duì)象的數(shù)據(jù)集中在其歸屬庫中,所以可以進(jìn)行任意聚合、連接等復(fù)雜處理。
每個(gè)庫都是全業(yè)務(wù)庫,同一業(yè)務(wù)對(duì)象的所有模塊處理都在一個(gè)庫中完成,不存在跨庫分布式事務(wù),數(shù)據(jù)強(qiáng)一致性丟還給數(shù)據(jù)庫單庫來保證。
但也存在以下硬傷:
產(chǎn)品線設(shè)計(jì)初期慎重挑選核心業(yè)務(wù)對(duì)象作為切分依據(jù),后期很難變更。
有些業(yè)務(wù)系統(tǒng)存在多個(gè)核心業(yè)務(wù)對(duì)象,不適合使用這種切分方式,如銀行線上線下整合核心。
以分庫分表切分和以核心業(yè)務(wù)對(duì)象切分是兩種主流的數(shù)據(jù)分布式設(shè)計(jì)范式,各有優(yōu)缺點(diǎn),應(yīng)在不同場景挑選合適的方式。
1.2. mysqlda
mysqlda是一款基于核心業(yè)務(wù)對(duì)象切分的Proxy模式的分布式MySQL數(shù)據(jù)庫中間件。
mysqlda優(yōu)勢(shì):
以核心業(yè)務(wù)對(duì)象切分方式的所有好處。
支持以核心業(yè)務(wù)對(duì)象定位MySQL歸屬庫(如開戶用手機(jī)號(hào)或郵箱),也支持核心業(yè)務(wù)對(duì)象的關(guān)聯(lián)對(duì)象(如開戶后的用戶ID、用戶名、賬號(hào))定位MySQL歸屬庫。
歸屬庫分配權(quán)重自動(dòng)調(diào)整,擴(kuò)容后新庫與老庫的分配權(quán)重也自動(dòng)調(diào)整,無需人工介入,使得所有歸屬庫的數(shù)據(jù)量盡量自動(dòng)均衡增長。
已包含數(shù)據(jù)庫網(wǎng)關(guān)高可用功能,當(dāng)一個(gè)歸屬庫當(dāng)前MySQL主服務(wù)器不可用時(shí)自動(dòng)切換到備服務(wù)器,支持多個(gè)備服務(wù)器。
與MySQL服務(wù)器之間的連接池機(jī)制,實(shí)現(xiàn)了連接復(fù)用和閑置清理,提高連接和切換性能。
通過在線重載配置文件,擴(kuò)容新增MySQL歸屬庫、調(diào)整MySQL服務(wù)器優(yōu)先列表等完全無感。
單體系統(tǒng)的數(shù)據(jù)分布式改造過程盡量無感。
2. 架構(gòu)與原理
2.1. 體系架構(gòu)
mysqlda數(shù)據(jù)庫中間件完全遵循MySQL通訊協(xié)議橋接應(yīng)用服務(wù)器集群和MySQL數(shù)據(jù)庫集群。
mysqlda內(nèi)部進(jìn)程結(jié)構(gòu)為“父-單子進(jìn)程”。
2.2. 工作原理
全量數(shù)據(jù)以核心業(yè)務(wù)對(duì)象切分到多個(gè)歸屬庫中,每個(gè)歸屬庫包含全業(yè)務(wù)表。一個(gè)歸屬庫由一個(gè)MySQL服務(wù)器列表(需部署為向下游同步數(shù)據(jù))組成,當(dāng)當(dāng)前MySQL服務(wù)器不可用時(shí)自動(dòng)切換到下一個(gè)。
MySQL數(shù)據(jù)庫集群預(yù)創(chuàng)建相同的連接用戶名、密碼,相同的數(shù)據(jù)庫名和應(yīng)用表結(jié)構(gòu),mysqlda預(yù)創(chuàng)建相同的連接用戶名、密碼。
啟動(dòng)mysqlda,從配置文件(etc/mysqlda.conf)中裝載連接用戶名、密碼,從保存文件(etc/mysqlda.save、etc/mysqlda.關(guān)聯(lián)對(duì)象類.save)中裝載已存在的核心業(yè)務(wù)對(duì)象、關(guān)聯(lián)對(duì)象 與 MySQL數(shù)據(jù)庫集群庫 歸屬庫關(guān)系信息。
應(yīng)用服務(wù)器調(diào)用標(biāo)準(zhǔn)MySQL連接函數(shù)/方法連接mysqlda,mysqlda會(huì)遵循MySQL通訊協(xié)議處理MySQL用戶登錄和密碼校驗(yàn)。
登錄成功后,所有DSL、DML操作前,應(yīng)用服務(wù)器發(fā)送mysqlda擴(kuò)展SQL選擇核心業(yè)務(wù)對(duì)象("select library (核心業(yè)務(wù)對(duì)象)")或關(guān)聯(lián)對(duì)象類、關(guān)聯(lián)對(duì)象("select library_by_correl_object (關(guān)聯(lián)對(duì)象類) (關(guān)聯(lián)對(duì)象)")以連接MySQL歸屬庫,mysqlda會(huì)查詢其已分配的MySQL庫核心業(yè)務(wù)對(duì)象或關(guān)聯(lián)對(duì)象類、關(guān)聯(lián)對(duì)象(如果沒有分配過則根據(jù)加權(quán)一致性哈希算法分配一個(gè)歸屬庫并持久化到保存文件中),從該MySQL歸屬庫對(duì)應(yīng)數(shù)據(jù)庫服務(wù)器有序列表中選擇第一個(gè)有效MySQL服務(wù)器及其連接池中選取空閑連接(如沒有緩存連接則新建一條連接),然后橋接對(duì)外和對(duì)內(nèi)連接結(jié)對(duì),開始處理后續(xù)所有DSL、DML操作。
后續(xù)操作中可以也發(fā)送mysqlda擴(kuò)展SQL再選擇核心業(yè)務(wù)對(duì)象或關(guān)聯(lián)對(duì)象類、關(guān)聯(lián)對(duì)象以調(diào)整MySQL歸屬庫服務(wù)器連接。
MySQL歸屬庫對(duì)應(yīng)一個(gè)數(shù)據(jù)庫服務(wù)器列表,如由MySQL數(shù)據(jù)庫1A(MASTER)、1B(SLAVE)、1C(SLAVE)、1D(SLAVE)組成,1A同步復(fù)制數(shù)據(jù)給1B、1C和1D,如果1A出現(xiàn)故障不能被mysqlda連接,mysqlda會(huì)依次嘗試連接1B、1C和1D,實(shí)現(xiàn)系統(tǒng)可用性。
應(yīng)用服務(wù)器發(fā)送mysqlda擴(kuò)展SQL綁定關(guān)聯(lián)對(duì)象類和關(guān)聯(lián)對(duì)象和核心業(yè)務(wù)對(duì)象("set correl_object 關(guān)聯(lián)對(duì)象類 關(guān)聯(lián)對(duì)象 核心業(yè)務(wù)對(duì)象"),mysqlda會(huì)保存該關(guān)系并持久化到保存文件中,供以后直接用關(guān)聯(lián)對(duì)象類、關(guān)聯(lián)對(duì)象定位MySQL歸屬庫。
2.3. 簡易案例
部署了三個(gè)MySQL歸屬庫,每個(gè)庫有主備兩臺(tái)MySQL服務(wù)器組成。
A用戶用手機(jī)號(hào)(核心業(yè)務(wù)對(duì)象)開戶,應(yīng)用服務(wù)器發(fā)送手機(jī)號(hào)13812345678給mysqlda請(qǐng)求定位歸屬庫("select library 13812341234"),mysqlda通過加權(quán)一致性哈希算法計(jì)算出該手機(jī)號(hào)(分配客戶)歸屬庫N并持久化到保存文件中,從歸屬庫N連接池中取出一個(gè)連接,把該連接與應(yīng)用服務(wù)器連接橋接,交換后面的所有SQL和處理結(jié)果。
開戶業(yè)務(wù)邏輯中創(chuàng)建了賬戶331234567890,,應(yīng)用服務(wù)器發(fā)送mysqlda擴(kuò)展SQL給mysqla("set correl_object account_no 331234567890 13812345678"),mysqlda綁定兩者關(guān)系并持久化到保存文件中。
A用戶后續(xù)處理請(qǐng)求,可以送手機(jī)號(hào)("select library 13812341234")或賬號(hào)("select library_by_correl_object account_no 331234567890")給mysqlda定位、連接用戶歸屬庫,該用戶的所有業(yè)務(wù)數(shù)據(jù)和業(yè)務(wù)處理都在該歸屬庫中完成。
2.4. 內(nèi)部數(shù)據(jù)實(shí)體和關(guān)系
一個(gè)MySQL歸屬庫(forward_instance)對(duì)應(yīng)一個(gè)MySQL數(shù)據(jù)庫服務(wù)器有序列表(forward_servers list)。
一個(gè)MySQL數(shù)據(jù)庫服務(wù)器有序列表(forward_servers list)下轄一個(gè)空閑連接池(unused_forward_session list)和一個(gè)工作連接池(forward_session list)。
一個(gè)核心業(yè)務(wù)對(duì)象可以綁定一個(gè)或多個(gè)關(guān)聯(lián)對(duì)象類(forward_correl_object_class)、關(guān)聯(lián)對(duì)象(forward_correl_object)。
一個(gè)核心業(yè)務(wù)對(duì)象或一個(gè)關(guān)聯(lián)對(duì)象類、關(guān)聯(lián)對(duì)象 與 MySQL歸屬庫 建立一個(gè)歸屬關(guān)系(forward_library)。
accepted_session是應(yīng)用服務(wù)器與mysqlda之間的通訊會(huì)話,forward_session是mysqlda與MySQL數(shù)據(jù)庫服務(wù)器之間的通訊會(huì)話,一旦一條連接上的MySQL歸屬庫被選定或切換,這兩個(gè)會(huì)話會(huì)被橋接起來。
