新聞中心
一、背景
電商業(yè)務場景,隨著平臺訂單規(guī)模的日益增長,訂單現(xiàn)有的存儲已經(jīng)沒辦法支撐后面業(yè)務的發(fā)展。在得物五彩石項目的時候就對訂單進行了分庫分表的拆分,為了解決分庫分表后賣家維度的查詢問題,單獨創(chuàng)建了一個賣家維度的訂單庫。

創(chuàng)新互聯(lián)建站專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務,包含不限于成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計、蕉城網(wǎng)絡推廣、微信平臺小程序開發(fā)、蕉城網(wǎng)絡營銷、蕉城企業(yè)策劃、蕉城品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務,您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)建站為所有大學生創(chuàng)業(yè)者提供蕉城建站搭建服務,24小時服務熱線:028-86922220,官方網(wǎng)址:www.cdcxhl.com
目前訂單分為買家和賣家兩個庫,賣家?guī)斓臄?shù)據(jù)是通過監(jiān)聽買家?guī)靊inlog異構(gòu)出來的一個庫。現(xiàn)在訂單主要有兩張表,分別是訂單的主表和子表。
在異構(gòu)的邏輯中,我們會對這兩張表的binlog消息進行處理,異構(gòu)成我們的賣家訂單表。在監(jiān)聽到插入的消息時,只會處理子表的插入消息,其余需要補充的主訂單表數(shù)據(jù)直接查詢主表。
查詢訂單主表的時候如果為空就會拋一個異常,依賴MQ的重試功能進行下一次重試,這是目前的邏輯。正常情況下訂單主表是不可能會出現(xiàn)查不到的情況,在19號凌晨的時候,有一大批訂單主表查不到的告警,于是通過關(guān)鍵字去日志平臺搜索,如下圖所示:
二、分析
2.1 業(yè)務影響
通過對報錯的消息進行排查,消息在二次重新投遞的時候,數(shù)據(jù)成功的保存到了數(shù)據(jù)庫里面,對業(yè)務無影響,只是會有異常告警。
2.2 主從延遲
目前的現(xiàn)象是第一次處理的時候,查詢主表為空,異常重試后就能查詢到數(shù)據(jù)。給我們的直覺就是數(shù)據(jù)庫的主從延遲產(chǎn)生的問題。
根據(jù)這個想法,去排查對應的代碼,發(fā)現(xiàn)從代碼層面是走的主庫查詢。這里順帶介紹下主從路由是如何實現(xiàn)的,項目中依賴了數(shù)據(jù)庫代理中間件彩虹橋的jar包,支持通過配置(bifrost.read-write-separate-model=SQL_READ_DEFAULT_MASTER)指定默認的讀寫分離模式。我們的模式默認是路由到主庫,如果有需要走從庫查詢的場景會在對應的dao方法上加一個注解進行標記。
然后會通過Mybatis的攔截器,對SQL進行處理,通過hint的方式將路由方式帶給彩虹橋,彩虹橋內(nèi)部根據(jù)指定的方式進行路由。
2.3 創(chuàng)單數(shù)據(jù)一致性
主從延遲的排除后,懷疑點在另一個方面。會不會創(chuàng)單的時候數(shù)據(jù)保存沒有在同一個事務里面,比如說子單先保存,然后再保存主單,此時子單的binlog肯定會早于主單,也就會存在查詢主單為空的情況。
這個也很快被否決了,如果是這個情況,那肯定是100%必現(xiàn)的場景,不是存在偶現(xiàn)的情況。其次,創(chuàng)單的代碼中對于數(shù)據(jù)存儲那塊是在一個事務內(nèi),所以不存在分批保存的情況。
2.4 數(shù)據(jù)庫內(nèi)部問題
排除了外部相關(guān)的問題,那么只剩下數(shù)據(jù)庫內(nèi)部的問題。接下來從binlog的寫入流程來看下是否存在有問題的地方,首先我們看下整體的流程,如下圖:
這里比較懷疑的點就在于redo log 二階段提交時,這個時候會把redo日志刷數(shù)據(jù)盤,也就是MySQL的存儲數(shù)據(jù)真正落庫。正常情況下,這個速度很快,當數(shù)據(jù)庫的IO很高的時候,刷盤的性能也會有所影響。所以在刷盤時稍微延遲了X毫秒的話,binlog已經(jīng)被應用給消費了,然后查詢不到。
根據(jù)告警的時間點,去看了從節(jié)點數(shù)據(jù)庫的監(jiān)控,那段時間確實IO較高,如下圖所示:
上面只是猜測,我們?nèi)绾稳ヲ炞C這個猜測是對的呢?
目前用的數(shù)據(jù)庫是主從模式,那么必然涉及到數(shù)據(jù)的復制,先簡單介紹下復制的幾種模式:
- 強同步
應用發(fā)起數(shù)據(jù)插入/更新/刪除操作在主實例執(zhí)行完成后,會將日志同步傳輸?shù)剿袀鋵嵗?,至?個備實例收到并存儲日志后,事務才完成提交。
- 半同步
應用發(fā)起數(shù)據(jù)插入/更新/刪除操作在主實例執(zhí)行完成后,會將日志同步傳輸?shù)?個備實例,備實例收到日志,事務就算完成了提交,不需要等待備實例執(zhí)行日志內(nèi)容。
- 異步
應用發(fā)起數(shù)據(jù)插入/更新/刪除請求,主實例完成操作后會立即響應應用,同時主實例向備實例異步復制數(shù)據(jù)。
目前我們數(shù)據(jù)庫用的是半同步的方式,在半同步里面支持兩種模式,分別是AFTER_COMMIT(5.6版本默認)和AFTER_SYNC(5.7版本才有,默認)。
1)AFTER_COMMIT
master將每個事務寫入binlog,傳遞到slave刷新到磁盤,同時master提交事務。master等待slave反饋收到relay log,只有收到ACK后master才將commit OK結(jié)果反饋給客戶端。
AFTER_COMMIT意味在master上,剛剛提交的事務對數(shù)據(jù)庫的修改,對其他事務是可見的。因此,如果在等待Slave ACK的時候crash了,那么會對其他事務出現(xiàn)幻讀,數(shù)據(jù)丟失的問題。
2)AFTER_SYNC
master將每個事務寫入binlog , 傳遞到slave刷新到磁盤。master等待slave反饋接收到relay log的ACK之后,再提交事務并且返回commit OK結(jié)果給客戶端。即使master crash,所有在master上已經(jīng)提交的事務都能保證已經(jīng)同步到slave的relay log中。
AFTER_SYNC在寫完binlog后,就開始傳輸,但此時還沒有提交事務,意味著當前這個事務對數(shù)據(jù)庫的修改,其他事務也是不可見的。所以不會出現(xiàn)幻讀,數(shù)據(jù)丟失風險。
我們目前是用的AFTER_SYNC模式,也就是說binlog寫入后,master會等待slave的反饋結(jié)果,然后才會commit,這里也就能正常解釋我們這個查詢不到的問題是什么原因了。原因就是master寫完binlog后在等待中,slave收到binlog后,由于IO高,寫入relay log比較慢,此時我們的訂閱平臺也相當于是一個從節(jié)點,同樣也收到了binlog,然后投遞給應用,應用這個時候去數(shù)據(jù)庫查詢,因為master還沒commit,自然就查不到。
三、解決方案
針對這個問題,解決方案有很多,梳理后發(fā)現(xiàn)這個場景其實不影響業(yè)務,將告警信息調(diào)整下,并不需要改造業(yè)務,如果想改也有一些可以解決的方案。
3.1 重試機制
對于這類場景,可以利用重試機制來解決。而目前的binlog監(jiān)聽也是利用MQ來投遞消息給業(yè)務方使用,可以直接依賴MQ的重試即可。
這個業(yè)務場景本身就是一個異步的過程,對實時性要求沒有那么高,其次對業(yè)務也不會有影響。第一次消息過來的時候沒有查到,終止流程,然后等到MQ重試,就可以查到數(shù)據(jù),完成整個流程。
3.2 延時消息
可以對訂閱平臺進行改造,在配置訂閱任務的時候可以指定監(jiān)聽到binlog后延遲多久發(fā)送給業(yè)務應用,這個延遲的處理直接用MQ的延時消息,這樣就可以將消息晚幾秒送到業(yè)務應用,也能解決問題。
延時消息也不能保證一定解決,重點在于延時的時間怎么設(shè)置比較合理。因為我們也不能保證數(shù)據(jù)庫從節(jié)點收到binlog后ack的時間有多長。還有就是如果配置的很長,要對現(xiàn)有場景的業(yè)務進行評估,是否能夠接受數(shù)據(jù)的延遲。
3.3 不依賴binlog
不依賴binlog指的是將消息改成業(yè)務動作觸發(fā)后發(fā)出的消息,比如創(chuàng)建訂單后,在代碼中通過MQ發(fā)出一條訂單創(chuàng)建的消息,里面包含了訂單的數(shù)據(jù)。這樣業(yè)務應用就可以不直接依賴binlog的消息,監(jiān)聽到業(yè)務消息的時候,事務必定已經(jīng)提交了,業(yè)務應用進行反查的時候數(shù)據(jù)已經(jīng)有了。
四、總結(jié)
數(shù)據(jù)庫可以說是作為研發(fā)同學必須要掌握的一個技能,但在日常工作中我們只需要掌握一些基本的語法就可以滿足開發(fā)需求,于是會忽略很多底層的原理。通過本文這個案例你會發(fā)現(xiàn)整個數(shù)據(jù)庫體系還有很多內(nèi)容值得去學習,試想一下,如果平時對主從復制的原理比較熟的話,問題排查起來也會簡單很多。
其次作為研發(fā),對于每一個問題都要有認真的態(tài)度,不能草草了事。從一個小問題,如果采取忽略的方式,就會失去求真的動力,從而失去很多可以學習的點。這個問題也是一樣,通過一步步排查,又積累了新的經(jīng)驗。
分享名稱:MySQL主從復制引發(fā)的這個問題,99%的人都不知道
分享地址:http://fisionsoft.com.cn/article/dpdoiho.html


咨詢
建站咨詢
