您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“MySQL主從延遲、讀寫分離問題如何解決”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當(dāng),希望這篇“MySQL主從延遲、讀寫分離問題如何解決”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
我們都知道互聯(lián)網(wǎng)數(shù)據(jù)有個特性,大部分場景都是 讀多寫少
,比如:微博、微信、淘寶電商,按照 二八原則
,讀流量占比甚至能達到 90%
結(jié)合這個特性,我們對底層的數(shù)據(jù)庫架構(gòu)也會做相應(yīng)調(diào)整。采用 讀寫分離
處理過程:
客戶端會集成 SDK,每次執(zhí)行 SQL 時,會判斷是 寫
或 讀
操作
如果是 寫
SQL,請求會發(fā)到 主庫
主數(shù)據(jù)庫執(zhí)行SQL,事務(wù)提交后,會生成 binlog
,并同步給 從庫
從庫
通過 SQL 線程回放 binlog
,并在從庫表中生成相應(yīng)數(shù)據(jù)
如果是 讀
SQL,請求會通過 負載均衡
策略,挑選一個 從庫
處理用戶請求
看似非常合理,細想?yún)s不是那么回事
主庫
與 從庫
是采用異步復(fù)制數(shù)據(jù),如果這兩者之間數(shù)據(jù)還沒有同步怎么辦?
主庫剛寫完數(shù)據(jù),從庫還沒來得及拉取最新數(shù)據(jù),讀
請求就來了,給用戶的感覺,數(shù)據(jù)丟了???
針對這個問題,今天,我們就來探討下有什么解決方案?
針對不用的業(yè)務(wù)訴求,區(qū)別性對待
如果是對數(shù)據(jù)的 實時性
要求不是很高,比如:大V有千萬粉絲,發(fā)布一條微博,粉絲晚幾秒鐘收到這條信息,并不會有特別大的影響。這時,可以走 從庫
。
如果對數(shù)據(jù)的 實時性
要求非常高,比如金融類業(yè)務(wù)。我們可以在客戶端代碼標(biāo)記下,讓查詢強制走主庫。
由于主從庫之間數(shù)據(jù)同步需要一定的時間間隔,那么有一種策略是延遲從從庫查詢數(shù)據(jù)。
比如:
select sleep(1) select * from order where order_id=11111;
在正式的業(yè)務(wù)查詢時,先執(zhí)行一個sleep 語句,給從庫預(yù)留一定的數(shù)據(jù)同步緩沖期。
因為是采用一刀切,當(dāng)面對高并發(fā)業(yè)務(wù)場景時,性能會下降的非常厲害,一般不推薦這個方案。
在從庫 執(zhí)行 命令 show slave status
查看 seconds_behind_master
的值,單位為秒,如果為 0,表示主備庫之間無延遲
比較主從庫的文件點位
還是執(zhí)行 show slave status
,響應(yīng)結(jié)果里有截個關(guān)鍵參數(shù)
Master_Log_File 讀到的主庫最新文件
Read_Master_Log_Pos 讀到的主庫最新文件的坐標(biāo)位置
Relay_Master_Log_File 從庫執(zhí)行到的最新文件
Exec_Master_Log_Pos 從庫執(zhí)行到的最新文件的坐標(biāo)位置
兩兩比較,上面的參數(shù)是否相等
比較 GTID 集合
Auto_Position=1 主從之間使用 GTID 協(xié)議
Retrieved_Gtid_Set 從庫收到的所有binlog日志的 GTID 集合
Executed_Gtid_Set 從庫已經(jīng)執(zhí)行完成的 GTID 集合
比較 Retrieved_Gtid_Set
和 Executed_Gtid_Set
的值是否相等
在執(zhí)行業(yè)務(wù)SQL操作時,先判斷從庫是否已經(jīng)同步最新數(shù)據(jù)。從而決定是操作主庫,還是操作從庫。
無論采用上面哪一種方案,如果主庫的寫操作頻繁不斷,那么從庫的值永遠跟不上主庫的值,那么讀流量永遠是打在了主庫上。
這個問題跟 MQ消息隊列 既要求高吞吐量又要保證順序是一樣的,從全局來看確實無解,但是縮小范圍就容易多了,我們可以保證一個分區(qū)內(nèi)的消息有序。
回到 主從庫
之間的數(shù)據(jù)同步問題,從庫查詢哪條記錄,我們只要保證之前對應(yīng)的寫binglog已經(jīng)同步完數(shù)據(jù)即可,可以不用管主從庫的所有的事務(wù)binlog 是否同步。
問題是不是一下簡單多了
在從庫執(zhí)行下面命令,返回是一個正整數(shù) M,表示從庫從參數(shù)節(jié)點開始執(zhí)行了多少個事務(wù)
select master_pos_wait(file, pos[, timeout]);
file 和 pos 表示主庫上的文件名和位置
timeout 可選, 表示這個函數(shù)最多等待 N 秒
master_pos_wait
返回結(jié)果無法與具體操作的數(shù)據(jù)行做關(guān)聯(lián),所以每次接收讀請求
時,從庫還是無法確認是否已經(jīng)同步數(shù)據(jù),方案實用性不高。
執(zhí)行下面查詢命令
阻塞等待,直到從庫執(zhí)行的事務(wù)中包含 gtid_set,返回 0
超時,返回 1
select wait_for_executed_gtid_set(gtid_set, 1);
MySQL 5.7.6 版本開始,允許在執(zhí)行完更新類事務(wù)后,把這個事務(wù)的 GTID 返回給客戶端。具體操作,將參數(shù)
session_track_gtids
設(shè)置為OWN_GTID
,調(diào)用 API 接口mysql_session_track_get_first
返回結(jié)果解析出 GTID
發(fā)起 寫
SQL 操作,在主庫成功執(zhí)行后,返回這個事務(wù)的 GTID
發(fā)起 讀
SQL 操作時,先在從庫執(zhí)行 select wait_for_executed_gtid_set (gtid_set, 1)
如果返回 0,表示已經(jīng)從庫已經(jīng)同步了數(shù)據(jù),可以在從庫執(zhí)行 查詢
操作
否則,在主庫執(zhí)行 查詢
操作
跟上面的 master_pos_wait
類似,如果 寫操作
與 讀操作
沒有上下文關(guān)聯(lián),那么 GTID 無法傳遞 。方案實用性不高。
高并發(fā)系統(tǒng),緩存作為性能優(yōu)化利器,應(yīng)用廣泛。我們可以考慮引入緩存作為緩沖介質(zhì)
客戶端 寫
SQL ,操作主庫
同步將緩存中的數(shù)據(jù)刪除
當(dāng)客戶端讀數(shù)據(jù)時,優(yōu)先從緩存加載
如果 緩存中沒有,會強制查詢主庫預(yù)熱數(shù)據(jù)
K-V 存儲,適用一些簡單的查詢條件場景。如果復(fù)雜的查詢,還是要查詢從庫。
參考 Redis Cluster 模式, 集群網(wǎng)絡(luò)拓撲通常是 3主 3從,主節(jié)點既負責(zé)寫,也負責(zé)讀。
通過水平分片,支持數(shù)據(jù)的橫向擴展。由于每個節(jié)點都是獨立的服務(wù)器,可以提高整體集群的吞吐量。
轉(zhuǎn)換到數(shù)據(jù)庫方面
常見的解決方式,是分庫分表,每次讀寫
都是操作主庫的一個分表,從庫只用來做數(shù)據(jù)備份。當(dāng)主庫發(fā)生故障時,主從切換,保證集群的高可用性。
讀到這里,這篇“MySQL主從延遲、讀寫分離問題如何解決”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。