從通信協(xié)議看MySQL客戶端與中間件設(shè)計(jì)
本文以UPSQL Proxy 2.4.0中關(guān)鍵的報(bào)文流式處理為例,介紹MySQL通信協(xié)議,以及與客戶端的關(guān)系。
MySQL通信協(xié)議協(xié)議介紹
在執(zhí)行MySQL查詢,如“selecet * from test”時(shí),MySQL的應(yīng)答包被稱為ResultSet,其為一組邏輯包(協(xié)議包),如圖1所示包含兩個(gè)部分:
- 1. 元數(shù)據(jù),包含如下數(shù)據(jù)包:
- - Field_Count:列的個(gè)數(shù)
- - Field:列的描述,一般為多個(gè)
- - Eof:在列信息描述,或數(shù)據(jù)發(fā)送完畢時(shí)候,用以標(biāo)記一段數(shù)據(jù)的發(fā)送結(jié)束。在較高版中,該數(shù)據(jù)包被取消。
- 2. 行數(shù)據(jù),包含:
- - Row:一行數(shù)據(jù)的內(nèi)容,多行時(shí)會(huì)出現(xiàn)多個(gè)
- - Err:描述錯(cuò)誤,出現(xiàn)錯(cuò)誤時(shí),為最后一個(gè)邏輯包
- 或
- - OK:在較高版本協(xié)議中,用以替換Eof包,用以傳輸更多信息
圖1 MySQL結(jié)果集報(bào)文結(jié)構(gòu)
客戶端庫(kù)接口介紹
由此MySQL CAPI中提供了兩套函數(shù)接口:
- - mysql_store_result/mysql_stmt_store_result
- - mysql_use_result
- 一般而言,這兩套接口的區(qū)別是:
- - mysql_store_result/mysql_stmt_store_result: 將結(jié)果存儲(chǔ)在應(yīng)用內(nèi)存
- - mysql_use_result: 數(shù)據(jù)保存在tcp buffer或數(shù)據(jù)庫(kù)server端
但從通信過程的角度來(lái)看:
- - mysql_store_result/mysql_stmt_store_result: 需要等待所有數(shù)據(jù)傳輸完畢,并且客戶端解析完畢
- - mysql_use_result: 簡(jiǎn)單而言只要得到row數(shù)據(jù)包,就可以向上層api返回?cái)?shù)據(jù)
- 所以,我們內(nèi)部將mysql_use_result稱為流式處理,流式處理有2大優(yōu)點(diǎn):
- - 應(yīng)用層響應(yīng)速度更快,因?yàn)椴恍枰却正R結(jié)果集
- - 內(nèi)存管理更可控,可以避免客戶端內(nèi)存不足
在mysql客戶端以及mysqldump命令中,有如下參數(shù):
- - --quik/-q,即使用mysql_use_result,進(jìn)行流式處理,可以避免mysqldump大數(shù)據(jù)量下oom
JDBC在設(shè)計(jì)上封裝性更高,一般而言其邏輯與CAPI的
- mysql_store_result/mysql_stmt_store_result處理邏輯一樣,但有2個(gè)方法可以將其轉(zhuǎn)換為流式處理模式:
- - 代碼層面:prepareStatement第2、3個(gè)參數(shù)設(shè)置為ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY
- - JDBC URL設(shè)置(不修改代碼):增加參數(shù)useCursorFetch=true&defaultFetchSize=-2147483648 (該方法在不同版本的jdbc驅(qū)動(dòng)上表現(xiàn)有區(qū)別,不建議采用)
API與協(xié)議解析的關(guān)系圖2所示:
▲ 圖2 API與協(xié)議解析
UPSQL Proxy中間件設(shè)計(jì)
在UPSQL Proxy 2.4.0以前使用的是阻塞模式,即往多個(gè)后端收齊結(jié)果集后,再向用戶應(yīng)答,這樣有2個(gè)缺點(diǎn):-
- 響應(yīng)時(shí)延延長(zhǎng)
- Proxy層內(nèi)存控制,導(dǎo)致生產(chǎn)環(huán)境不支持大于分庫(kù)下10w行以上數(shù)據(jù)量返回
UPSQL Proxy 2.4.0實(shí)現(xiàn)了流式處理,簡(jiǎn)單而言就是,將行信息盡快以流的形式發(fā)給客戶端而不是等中間件收齊后發(fā)送,邏輯如圖3所示:
▲ 圖3 UPSQL Proxy的流式處理
即在分庫(kù)場(chǎng)景下,會(huì)并發(fā)訪問各個(gè)數(shù)據(jù)節(jié)點(diǎn),當(dāng)?shù)玫揭粋€(gè)完整的元數(shù)據(jù)后,就可以立刻返回給請(qǐng)求方,之后接收到行數(shù)據(jù)后,都可以及時(shí)的返回給請(qǐng)求方,以此降低中間件的內(nèi)存需求,同時(shí)提高客戶端的相應(yīng)速度。
總結(jié)
本文介紹了銀聯(lián)自研中間件UPSQL Proxy早前的一次關(guān)鍵功能迭代,希望能讓大家感受到MySQL協(xié)議的魅力。
福利時(shí)間(目前投遞會(huì)有作者的內(nèi)推機(jī)會(huì)哦 🙌🏻🙌🏻🙌🏻):
中國(guó)銀聯(lián)云計(jì)算中心社會(huì)招聘崗位正在火熱招錄中,目前開放投遞的崗位如下:
1、運(yùn)營(yíng)服務(wù)
2、系統(tǒng)運(yùn)維
3、操作系統(tǒng)開發(fā)
4、數(shù)據(jù)庫(kù)開發(fā)(云計(jì)算方向)
5、開源組件
6、綜合文秘
有意向者可打開鏈接【可復(fù)制到瀏覽器或者點(diǎn)擊閱讀原文】 https://join.unionpay.com 選擇“社會(huì)招聘”分類進(jìn)行投遞。【注:內(nèi)推請(qǐng)?zhí)顚?周家晶及工號(hào):01362912為推薦人】