當(dāng)前位置:首頁(yè) >  站長(zhǎng) >  數(shù)據(jù)庫(kù) >  正文

Mysql讀寫(xiě)分離過(guò)期常用解決方案

 2020-11-16 11:40  來(lái)源: 腳本之家   我來(lái)投稿 撤稿糾錯(cuò)

  域名預(yù)訂/競(jìng)價(jià),好“米”不錯(cuò)過(guò)

這篇文章主要介紹了Mysql讀寫(xiě)分離過(guò)期常用解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

mysql讀寫(xiě)分離的坑

讀寫(xiě)分離的主要目標(biāo)是分?jǐn)傊鲙?kù)的壓力,由客戶(hù)端選擇后端數(shù)據(jù)庫(kù)進(jìn)行查詢(xún)。還有種架構(gòu)就是在MYSQL和客戶(hù)端之間有一個(gè)中間代理層proxy,客戶(hù)端之連接proxy,由proxy根據(jù)請(qǐng)求類(lèi)型和上下文決定請(qǐng)求的分發(fā)路由。

客戶(hù)端直連方案:因?yàn)樯倭艘粚觩roxy轉(zhuǎn)發(fā),所以查詢(xún)性能稍微好一點(diǎn)兒,并且整體架構(gòu)簡(jiǎn)單,排查問(wèn)題更方便。但是這種方案,由于要了解后端部署細(xì)節(jié),所以在出現(xiàn)主備切換、庫(kù)遷移等操作的時(shí)候,客戶(hù)端都會(huì)感知到,并且需要調(diào)整數(shù)據(jù)庫(kù)連接信息。

帶proxy架構(gòu):對(duì)客戶(hù)端比較友好??蛻?hù)端不需要關(guān)注后端細(xì)節(jié),連接維護(hù)、后端信息維護(hù)等工作,都是由proxy完成的。但這樣的話(huà),對(duì)后端維護(hù)團(tuán)隊(duì)的要求會(huì)更高。

無(wú)論使用哪種架構(gòu),由于主從可能存在延遲,客戶(hù)端執(zhí)行完一個(gè)更新事務(wù)后馬上發(fā)起查詢(xún),如果查詢(xún)選擇的是從庫(kù)的話(huà),就有可能讀到剛剛的事務(wù)更新之前的狀態(tài)。這種“在從庫(kù)上會(huì)讀到系統(tǒng)的一個(gè)過(guò)期狀態(tài)”的現(xiàn)象,我們暫且稱(chēng)之為“過(guò)期讀”。

方案一:強(qiáng)制走主庫(kù)方案

將查詢(xún)請(qǐng)求分為兩類(lèi):

對(duì)于必須要拿到最新結(jié)果的請(qǐng)求,強(qiáng)制將其發(fā)到主庫(kù)上。比如,在一個(gè)交易平臺(tái)上,賣(mài)家發(fā)布商品以后,馬上要返回主頁(yè)面,看商品是否發(fā)布成功。那么,這個(gè)請(qǐng)求需要拿到最新的結(jié)果,就必須走主庫(kù)。

對(duì)于可以讀到舊數(shù)據(jù)的請(qǐng)求,才將其發(fā)到從庫(kù)上。在這個(gè)交易平臺(tái)上,買(mǎi)家來(lái)逛商鋪?lái)?yè)面,就算晚幾秒看到最新發(fā)布的商品,也是可以接受的。那么,這類(lèi)請(qǐng)求就可以走從庫(kù)。這個(gè)方案的最大問(wèn)題在于會(huì)碰到所有查詢(xún)都不是“過(guò)期讀”的需求,比如金融類(lèi)業(yè)務(wù),這樣就要放棄讀寫(xiě)分離,所有的壓力都在主庫(kù)。采用以下方案。

方案二:Sleep方案

主庫(kù)更新后,讀從庫(kù)之前先sleep一下,類(lèi)似執(zhí)行了select sleep(1)命令,這個(gè)方案的假設(shè)是,大多數(shù)情況下主備延遲在1秒之內(nèi),做一個(gè)sleep可以有很大概率拿到最新的數(shù)據(jù)。

以賣(mài)家發(fā)布商品為例,商品發(fā)布后,用Ajax直接把客戶(hù)端輸入的內(nèi)容作為“新的商品”顯示在頁(yè)面上,而不是真正地去數(shù)據(jù)庫(kù)做查詢(xún)。這樣,賣(mài)家就可以通過(guò)這個(gè)顯示,來(lái)確認(rèn)產(chǎn)品已經(jīng)發(fā)布成功了。等到賣(mài)家再刷新頁(yè)面,去查看商品的時(shí)候,其實(shí)已經(jīng)過(guò)了一段時(shí)間,也就達(dá)到了sleep的目的,進(jìn)而也就解決了過(guò)期讀的問(wèn)題。

方案三:判斷主備無(wú)延遲方案:

第一種方法:先用show slave status結(jié)果里的seconds_behind_master參數(shù)的值,可以用來(lái)衡量主備延遲時(shí)間的長(zhǎng)短。先判斷這個(gè)參數(shù)值是否為0,如果不為0,必須等到這個(gè)參數(shù)變?yōu)?才能執(zhí)行請(qǐng)求。

第二種方法:對(duì)比位點(diǎn)確保主備無(wú)延遲。

Master_Log_File和Read_Master_Log_Pos,表示的是讀到的主庫(kù)的最新位點(diǎn);

Relay_Master_Log_File和Exec_Master_Log_Pos,表示的是備庫(kù)執(zhí)行的最新位點(diǎn)。

如果Master_Log_File和Relay_Master_Log_File、Read_Master_Log_Pos和Exec_Master_Log_Pos這兩組值完全相同,就表示接收到的日志已經(jīng)同步完成。

第三種方法:對(duì)比GTID(全局事物ID)確保主備無(wú)延遲

Auto_Position=1 ,表示這對(duì)主備關(guān)系使用了GTID協(xié)議。

Retrieved_Gtid_Set,是備庫(kù)收到的所有日志的GTID集合;

Executed_Gtid_Set,是備庫(kù)所有已經(jīng)執(zhí)行完成的GTID集合。

如果這兩個(gè)集合相同,表示備庫(kù)接收到的日志都已經(jīng)同步完成。

方案四:等主庫(kù)位點(diǎn)方案

select master_pos_wait(file, pos[, timeout]);

這條命令是在從庫(kù)執(zhí)行的 ,參數(shù)file和pos指的是主庫(kù)上的文件名和位置,timeout表示這個(gè)函數(shù)最多等待N秒。

這個(gè)命令正常返回的結(jié)果是一個(gè)正整數(shù)M,表示從命令開(kāi)始執(zhí)行,到應(yīng)用完file和pos表示的binlog位置,執(zhí)行了多少事務(wù)。

如果備庫(kù)同步線(xiàn)程發(fā)生異常,則返回null

如果等待超過(guò)N秒,就返回-1

如果剛開(kāi)始執(zhí)行就發(fā)現(xiàn)已經(jīng)執(zhí)行過(guò)了,則返回0

如圖:先執(zhí)行trx1,再執(zhí)行一個(gè)查詢(xún)請(qǐng)求的邏輯,要保證能夠查到正確的數(shù)據(jù),我們可以使用

這個(gè)邏輯

1. trx1事物更新完成后,馬上執(zhí)行show master status得到當(dāng)前主庫(kù)執(zhí)行到的File和Position;

2. 選定一個(gè)從庫(kù)執(zhí)行查詢(xún)語(yǔ)句;

3. 在從庫(kù)上執(zhí)行select master_pos_wait(File, Position, 1);

4. 如果返回值是>=0的正整數(shù),則在這個(gè)從庫(kù)執(zhí)行查詢(xún)語(yǔ)句;

5. 否則,到主庫(kù)執(zhí)行查詢(xún)語(yǔ)句。

這里我們假設(shè),這條select查詢(xún)最多在從庫(kù)上等待1秒。那么,如果1秒內(nèi)master_pos_wait返回

一個(gè)大于等于0的整數(shù),就確保了從庫(kù)上執(zhí)行的這個(gè)查詢(xún)結(jié)果一定包含了trx1的數(shù)據(jù)。

5到主庫(kù)執(zhí)行查詢(xún)語(yǔ)句,是這類(lèi)方案常用的退化機(jī)制。因?yàn)閺膸?kù)的延遲時(shí)間不可控,不能無(wú)

限等待,所以如果等待超時(shí),就應(yīng)該放棄,然后到主庫(kù)去查。按照我們?cè)O(shè)定不允許過(guò)期讀的要求,就只有兩種選擇,一種是超時(shí)放棄,一種是轉(zhuǎn)到主庫(kù)查詢(xún)。

并發(fā)連接和并發(fā)查詢(xún)

innodb_thread_concurrency參數(shù)是控制innodb的并發(fā)線(xiàn)程上限。一旦超過(guò)這個(gè)數(shù)值,新請(qǐng)求就會(huì)進(jìn)入等待。

show processlist看到的幾千個(gè)連接,是值并發(fā)連接,而當(dāng)前正在執(zhí)行的語(yǔ)句,才是并發(fā)查詢(xún)。并發(fā)連接影響不大,只是會(huì)多占內(nèi)存,而并發(fā)查詢(xún)才是CPU殺手。

在線(xiàn)程進(jìn)入鎖等待以后,并發(fā)線(xiàn)程的計(jì)數(shù)會(huì)建議,也就是等行鎖的線(xiàn)程是不算在并發(fā)查詢(xún)里的。因?yàn)樗却呀?jīng)不吃CPU了

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

來(lái)源:腳本之家

鏈接:https://www.jb51.net/article/195367.htm

申請(qǐng)創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!

相關(guān)標(biāo)簽
mysql

相關(guān)文章

  • MySQL5.7 集群配置的步驟

    這篇文章主要介紹了MySQL5.7集群配置的步驟,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下

    標(biāo)簽:
    mysql
  • MySQL中觸發(fā)器和游標(biāo)的介紹與使用

    這篇文章主要給大家介紹了關(guān)于MySQL中觸發(fā)器和游標(biāo)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • MySQL中exists、in及any的基本用法

    這篇文章主要給大家介紹了關(guān)于MySQL中exists、in及any的基本用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • MySQL正確修改最大連接數(shù)的3種方案

    這篇文章主要給大家介紹了關(guān)于MySQL正確修改最大連接數(shù)的3種方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • 教你怎么在Windows系統(tǒng)上手動(dòng)搭建MySql數(shù)據(jù)庫(kù)

    1.已經(jīng)購(gòu)買(mǎi)好的騰訊云輕量應(yīng)用服務(wù)器。2.作者本次演示使用的系統(tǒng)是WindowsServer2019,其他windows版本也可以,操作流程大同小異。3.使用Windows遠(yuǎn)程桌面連接騰訊云輕量服務(wù)器。

熱門(mén)排行

信息推薦