《MySQL——如何解決一主多從的讀寫分離的過期讀問題》

目錄

    • 兩種架構
    • 兩種架構特點
    • 強制走主庫方案
    • Sleep方案
    • 判斷主備無延遲方案
    • 配合semi-sync
    • 等主庫位點方案
    • GTID方案

兩種架構

基于一主多從的讀寫分離,如何處理主備延遲導致的讀寫分離問題。

讀寫分離的主要目標:分攤主庫壓力。

有兩種架構:

1、客戶端主動做負載均衡,把數據庫的連接信息放在客戶端的連接層。由客戶端選擇后端數據庫進行查詢。
在這里插入圖片描述

2、MySQL和客戶端之間加上一個中間代理層proxy,客戶端只連接proxy,由proxy根據請求類型和上下文決定請求的分發路由
在這里插入圖片描述

兩種架構特點

1、客戶端直連方案,少了一層proxy轉發,查詢性能較好,結構也比較簡單。

由于要了解后端部署細節,所以在出現主備切換、庫遷移等操作時,客戶端都會感知到,并且調整數據庫連接信息。客戶端再分配一個負責管理后端的組件,讓業務端只注重于業務邏輯開發

2、帶proxy的架構,使客戶端不需要關注后端細節。

連接維護、后端信息維護等工作,都是由proxy完成的。但是架構整體相對復雜

兩種架構都會遇到"過期讀"問題:

由于主從可能存在延遲,客戶端執行完一個更新事務后馬上發起查詢,如果查詢選擇的是從庫的話,就有可能讀到的是事務更新之前的狀態。

客戶端希望的是查詢從庫的數據結果和查主庫的數據結果是一樣的。

下面是解決方案:

強制走主庫方案;
sleep方案;
判斷主備無延遲方案;
配合semi_sync方案;
等主庫位點方案;
等GTID方案;

實際應用中,這幾個方案可以混合使用。

比如,現在客戶端對請求做分類,區分哪些請求可以接受過期讀,哪些請求完全不餓能接受過期讀。然后,對于不能接受過期讀的語句,再使用等GTID或等位點的方案,

過期讀本質上是由一寫多讀導致的,為了避免過期讀,只有兩種選擇:

1、超時放棄

2、轉到主庫查詢

強制走主庫方案

將查詢請求做分類:

1、對于必須要拿到最新結果的請求,強制將其發到主庫上。

2、對于可以讀到舊數據的請求,才將其發到從庫上。

這種方案雖然取巧,但是好用。

此方案最大的問題在于:當遇到實時性比較高要求的業務需求,就要放棄讀寫分離,所有的讀寫壓力都在主庫,等同于放棄了擴展性。

Sleep方案

主庫更新后,讀從庫之前先sleep。如執行一條select sleep(1)命令。

方案假設:大多數情況下主備延遲在1s之內,做一個sleep可以有很大概率拿到到最新的數據

該方案不精確:

1、如果這個查詢請求0.1s就能在從庫拿到正確結果,sleep(1)也會等1s

2、如果延遲超過1s,還是會出現過期讀

判斷主備無延遲方案

要確保備庫無延遲有三種做法:

show slave status結果里的seconds_behind_master參數可以用來衡量主備延遲時間的長短。

第一種方法

每次從庫執行查詢請求前,先判斷seconds_behind_master是否等于0,如果不等于0就要等到這個參數變為0才執行查詢操作。

第二種方法

比對位點確保主備無延遲。

  • Master_Log_File 和 Read_Master_Log_Pos,表示的是讀到的主庫的最新位點;

  • Relay_Master_Log_File 和 Exec_Master_Log_Pos,表示的是備庫執行的最新位點;

如果Master_Log_File 和 Relay_Master_Log_File 值相同,且Read_Master_Log_Pos和Exec_Master_Log_Pos相同,說明接受到的日志已經同步完成。

第三種方法

對比GTID集合確保主備無延遲

Auto_Position = 1,表示這對主備關系使用了GTID協議
Retrieved_Gtid_Set,是備庫收到的所有日志的GTID集合
Executed_Gtid_Set,是備庫所有已經執行完成的GTID集合

如果兩個集合相同,表示備庫接收到了日志都已同步完成。

一個事務的binlog在主備庫之間的狀態:

1、主庫執行完成,寫入binlog,并反饋給客戶端;

2、binlog被從主庫發送給備庫,備庫收到

3、在備庫執行binlog完成。

我們上面判斷主備無延遲的邏輯是"備庫收到的日志都執行完成了",但是有一部分日志會處于客戶端已經收到提交確認,而備庫還沒收到日志的狀態。
在這里插入圖片描述

在主庫上執行完成了三個事務trx1、trx2、trx3,前兩個已經傳到從庫并且執行完成了。trx3在主庫執行完成,并且已經回復給客戶端,但是還沒有傳到從庫中。此時在從庫B上執行查詢請求,按照上面的三個方法的邏輯,從庫會認為已經沒有同步延遲,但是還是會查不到trx3.

配合semi-sync

解決上面的問題,要引入半同步復制,即semi-sync replication

semi-sync是這樣做的:

1、事務提交的時候,主庫把binlog發給從庫;

2、從庫收到binlog以后,發回給主庫一個ack,表示收到了

3、主庫收到這個ack以后,才能給客戶端返回"事務完成"的確認

也就是說,如果啟用了semi-sync,就說明所有給客戶端發送過確認的事務備庫都已經收到了日志。

semi-sync+位點的判斷方案,在一主一備場景是成立的,在一主多從場景中,主庫只要等到一個從庫的ack,就開始給客戶端返回確認。

但是這樣會出現問題:

1、查詢落到沒有收到最新日志的從庫上,產生過期讀。

2、業務更新高峰期,主庫的位點或者GTID集合更新很快,兩個位點的等值判斷一直不成立,很可能出現從庫上遲遲無法響應查詢請求的情況

等主庫位點方案

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

這個命令邏輯如下:

1、在從庫執行

2、參數file和pos指的是主庫的文件名和位置

3、timeout可選,設置為正整數N表示這個函數最多等待N秒

4、返回正整數M,表示從命令開始執行,到應用完file和pos表示的binlog位置執行了多少事務

返回值還有一下異常結果:

1、NULL,執行期間,備庫同步線程發生異常。

2、-1,等待時間超過N秒

3、0,這個位置已經執行過了

使用該方法步驟:

1、事務trx1更新完后,馬上執行show master status得到當前主庫執行到的File和Position

2、選定一個從庫執行查詢語句

3、在從庫上執行select master_pos_wait(File,Position,1)

4、如果返回值是>=0的正整數,則在這個從庫執行查詢語句

5、否則到主庫執行查詢語句。

假設,每條select最多在從庫上等待1s,如果1s內master_pos_wait返回一個>=0的整數,就確保了從庫上執行的這個查詢結果一定包含trx1數據。

如果每個從庫都延遲超過了1s,查詢壓力都會跑到主庫上去。

但是為了不允許過期讀,只有兩種方法:1、超時放棄 2、轉到主庫查詢

GTID方案

 select wait_for_executed_gtid_set(gtid_set, 1);

命令邏輯是:

1、等待,直到這個庫執行的事務中包含傳入的gtid_set,返回0

2、超時返回1

等GTID的執行流程為:

1、事務trx1更新后,從返回包直接獲取這個事務GTID,記為gtid1

2、選定一個從庫執行查詢語句

3、在從庫上執行select wait_for_executed_gtid_set(gtid1,1)

4、如果返回值為0,在這個從庫中執行查詢語句

5、否則,到主庫執行查詢語句

tips:使MySQL在執行事務后,返回包中帶上GTID:

( 1. session_track_gtids設置為OWN_GTID 2. 通過API接口獲取mysql_session_track_get_first解析出gtid的值 )

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377176.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377176.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377176.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

json/ 發送形式_24/7的完整形式是什么?

json/ 發送形式24/7:二十四 (24/7: Twenty-Four Seven) 24/7 or 24-7 service, which generally marked "twenty-four seven" is service that is existing at any time and typically, every day in trade business and industry. Substitute orthograph…

《MySQL tips:并發查詢與并發連接區別》

并發連接與并發查詢,并不是一個概念。 在執行show processlist的結果里,看到了幾千個連接,指的是并發連接。 而"當前正在執行"的語句,才是并發查詢。 并發連接數多影響的是內存。 并發查詢太高對CPU不利。一個機器的…

對上拉下拉電阻的作用作個總結(想了解的過來看看)(轉載)

轉自:http://www.amobbs.com/thread-5475279-1-3.html 一、定義:上拉就是將不確定的信號通過一個電阻嵌位在高電平!電阻同時起限流作用!下拉同理!上拉是對器件注入電流,下拉是輸出電流;弱強只是…

給用戶傳入的變量進行轉義操作

先看代碼實現: /* 對用戶傳入的變量進行轉義操作。*/ if (!get_magic_quotes_gpc()) {if (!empty($_GET)){$_GET addslashes_deep($_GET);}if (!empty($_POST)){$_POST addslashes_deep($_POST);}$_COOKIE addslashes_deep($_COOKIE);$_REQUEST addslashes_…

《MySQL——外部檢測與內部統計 判斷 主庫是否出現問題》

目錄select1判斷查表判斷更新判斷外部檢測弊端內部統計一主一備的雙M架構里,主備切換只需要把客戶端流量切換到備庫。 在一主多從的架構里,主備切換要把客戶端流量切換到備庫,也需要把從庫接到新主庫上。 切換有兩種場景:1、主動…

NIM的完整形式是什么?

NIM:無內部消息 (NIM: No Internal Message) NIM is an abbreviation of "No Internal Message". NIM是“無內部消息”的縮寫。 It is an expression, which is commonly used in the Gmail platform. It is written in the subject of the mail, if the…

[Json] C#ConvertJson|List轉成Json|對象|集合|DataSet|DataTable|DataReader轉成Json (轉載)...

點擊下載 ConvertJson.rar 本類實現了 C#ConvertJson|List轉成Json|對象|集合|DataSet|DataTable|DataReader轉成Json|等功能大家先預覽一下 請看代碼 /// <summary> /// 類說明&#xff1a;Assistant /// 編 碼 人&#xff1a;蘇飛 /// 聯系方式&#xff1a;361983679 …

let 只能在嚴格模式下嗎_LET的完整形式是什么?

let 只能在嚴格模式下嗎LET&#xff1a;今天早早離開 (LET: Leaving Early Today) LET is an abbreviation of "Leaving Early Today". LET是“ Leaveing Today Today”的縮寫 。 It is an expression, which is commonly used in the Gmail platform. It is writt…

js 遮罩層 loading 效果

//調用方法 //關閉事件<button οnclickLayerHide()>關閉</button>&#xff0c;在loadDiv(text)中&#xff0c;剔除出來 //調用LayerShow(text)&#xff0c;text為參數&#xff0c;可以寫入想要寫入的提示語 //本方法在調用時會自動生成一個添加到body的div&#x…

centos6.5安裝配置LDAP服務[轉]

centos6.5安裝配置LDAP服務[轉] 安裝之前查一下 1find / -name openldap*centos6.4默認安裝了LDAP&#xff0c;但沒有裝ldap-server和ldap-client 于是yum安裝 1su root2yum install -y openldap openldap-servers openldap-clients不建議編譯源碼包&#xff0c;有依賴比較麻煩…

《MySQL——恢復數據-誤刪行、表、庫》

目錄誤刪行事前預防誤刪行數據方法誤刪表/庫延遲復制備庫事前預防誤刪庫/表方法傳統的架構不能預防誤刪數據&#xff0c;因為主庫的一個drop table命令&#xff0c;會通過binlog傳給所有從庫和級聯從庫&#xff0c;進而導致整個集群的實例都會執行這個命令。 MySQL相關的誤刪除…

python圖例位置_Python | 圖例位置

python圖例位置Legends are one of the key components of data visualization and plotting. Matplotlib can automatically define a position for a legend in addition to this, it allows us to locate it in our required positions. Following is the list of locations…

Freemarker中遍歷List實例

Freemarker中如何遍歷List摘要&#xff1a;在Freemarker應用中經常會遍歷List獲取需要的數據&#xff0c;并對需要的數據進行排序加工后呈現給用戶。那么在Freemarker中如何遍歷List&#xff0c;并對List中數據進行適當的排序呢&#xff1f;通過下文的介紹&#xff0c;相信您一…

工作總結:文件對話框的分類(C++)

原文地址&#xff1a;http://www.jizhuomi.com/software/173.html 文件對話框分為打開文件對話框和保存文件對話框&#xff0c;相信大家在Windows系統中經常見到這兩種文件對話框。例如&#xff0c;很多編輯軟件像記事本等都有“打開”選項&#xff0c;選擇“打開”后會彈出一個…

《MySQL——Innodb改進LRU算法》

Innodb改進LRU.算法&#xff0c;實質上將內存鏈表分成兩段。 靠近頭部的young和靠近末尾的old&#xff0c;取5/12段為分界。 新數據在一定時間內只能在old段的頭部&#xff0c;當在old段保持了一定的時間后被再次訪問才能升級到young。 實質上是分了兩段lru&#xff0c;這樣做的…

nfc/nfc模式_NFC的完整形式是什么?

nfc/nfc模式NFC&#xff1a;沒有進一步評論 (NFC: No Further Comment) NFC is an abbreviation of "No Further Comment". NFC是“沒有進一步評論”的縮寫 。 It is an expression, which is commonly used in messaging or chatting on social media networking s…

dx小記(2)

1.構造一個平截臺體&#xff08;Frustum&#xff09; 最近距離-projMatirx.43/projMatrix.33 projMatrix。33 深度/&#xff08;深度-最近距離&#xff09; projMatrix。44-最近距離*&#xff08;深度/&#xff08;深度-最近距離&#xff09;&#xff09; FrustumMatrix proje…

jQuery: 整理4---創建元素和添加元素

1.創建元素&#xff1a;$("內容") const p "<p>這是一個p標簽</p>" console.log(p)console.log($(p)) 2. 添加元素 2.1 前追加子元素 1. 指定元素.prepend(內容) -> 在指定元素的內部的最前面追加內容&#xff0c;內容可以是字符串、…

Design a high performance cache for multi-threaded environment

如何設計一個支持高并發的高性能緩存庫 不 考慮并發情況下的緩存的設計大家應該都比較清楚&#xff0c;基本上就是用map/hashmap存儲鍵值&#xff0c;然后用雙向鏈表記錄一個LRU來用于緩存的清理。這篇文章 應該是講得很清楚http://timday.bitbucket.org/lru.html。但是考慮到高…

《MySQL——join語句優化tips》

目錄要不要用joinJoin驅動表選擇Multi-Range Read優化Batched Key Access &#xff08;BKA&#xff09;對NLJ進行優化BNL算法性能問題BNL轉BKA要不要用join 1、如果使用的是Index Nested-Loop Join算法&#xff0c;即可以用上被驅動表的索引&#xff0c;可以用 2、如果使用的…