網(wǎng)上有很多關(guān)于pos機(jī)數(shù)據(jù)超時(shí),MySQL主從數(shù)據(jù)不一致的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)數(shù)據(jù)超時(shí)的問(wèn)題,今天pos機(jī)之家(m.mxllmx.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!
本文目錄一覽:
pos機(jī)數(shù)據(jù)超時(shí)
主從數(shù)據(jù)不一致問(wèn)題先介紹下問(wèn)題產(chǎn)生的背景。
在MySQL 一主多從的架構(gòu)中,主要有兩種,一種是通過(guò)客戶端直連,一種是通過(guò)代理 prxoy 間接連接。
客戶端直連模式下一般會(huì)把數(shù)據(jù)庫(kù)的連接信息放在客戶端的連接層,客戶端做負(fù)載均衡,由客戶端來(lái)選擇后端數(shù)據(jù)庫(kù)進(jìn)行查詢。通過(guò)代理的模式下 MySQL 和客戶端之間有一個(gè)中間代理層 proxy,客戶端直連接 proxy, 由 proxy 根據(jù)請(qǐng)求類型和上下文決定請(qǐng)求的分發(fā)路由。
客戶端直連和帶 proxy 的讀寫分離架構(gòu),各有哪些特點(diǎn)。
客戶端直連方案,整體架構(gòu)簡(jiǎn)單,排查問(wèn)題方便。但是這種方案,由于要了解后端部署細(xì)節(jié),所以在出現(xiàn)主備切換、庫(kù)遷移等操作的時(shí)候,處理起來(lái)比較麻煩,對(duì)開(kāi)發(fā)人員要求高。直連 proxy 的架構(gòu),對(duì)客戶端比較友好??蛻舳瞬恍枰P(guān)注后端細(xì)節(jié),但是 proxy 也需要有高可用架構(gòu),架構(gòu)更復(fù)雜,對(duì)運(yùn)維團(tuán)隊(duì)要求更高。目前趨勢(shì)是直連 proxy 的方向發(fā)展,具體取舍取決于自身情況。
帶來(lái)的問(wèn)題無(wú)論哪種架構(gòu),都會(huì)遇到主從數(shù)據(jù)不一致的問(wèn)題:由于主從同步可能存在延遲,客戶端執(zhí)行完一個(gè)更新事務(wù)后馬上發(fā)起查詢,如果查詢選擇的是從庫(kù)的話,就有可能讀到剛剛的事務(wù)更新之前的狀態(tài)。如何解決呢?
在進(jìn)行讀寫分離的同時(shí),解決主從同步中數(shù)據(jù)不一致的問(wèn)題,主要有幾種思路,一是從業(yè)務(wù)層面解決,二是從檢測(cè)主從同步的差異上解決,三也是最根本的方式——從主從之間數(shù)據(jù)復(fù)制方式解決。按照這三種指導(dǎo)思想,我總結(jié)了一下有以下幾種方案。
全部走主庫(kù)方案先說(shuō)一種最為廣泛使用的方案,也就是二狗的回答。
如果是在同一數(shù)據(jù)庫(kù)中對(duì)數(shù)據(jù)進(jìn)行更新的時(shí)候,可以對(duì)記錄加寫鎖,這樣在讀取的時(shí)候就不會(huì)發(fā)生數(shù)據(jù)不一致的情況。所以我們可以根據(jù)業(yè)務(wù)場(chǎng)景來(lái)做區(qū)分。如果是需要寫完之后必須讀區(qū)到準(zhǔn)確數(shù)據(jù)的場(chǎng)景,可以直接全部走主庫(kù),比如訂單支付、金融業(yè)務(wù)等強(qiáng)一致性場(chǎng)景;如果業(yè)務(wù)允許讀到舊數(shù)據(jù),可以在讀的時(shí)候查詢從庫(kù)。
這樣的話你可能覺(jué)得并沒(méi)有真正解決主從不一致的問(wèn)題,但其實(shí)在實(shí)際生產(chǎn)中,大多數(shù)情況下都這么解決的。優(yōu)點(diǎn)是簡(jiǎn)單成本低,不需要復(fù)雜架構(gòu)。缺點(diǎn)也很明顯,如果業(yè)務(wù)一致性要求很高,很多讀都會(huì)在主庫(kù)進(jìn)行,并沒(méi)有真正的讀寫分離減輕主庫(kù)壓力,讀寫分離成了擺設(shè)。
延遲查詢方案比如主庫(kù)更新一條數(shù)據(jù)以后,查詢從庫(kù)數(shù)據(jù)的時(shí)候后端接口可以線sleep一段時(shí)間,比如絕大多數(shù)主從同步都可以在1s內(nèi)完成,那就可以sleep一秒鐘的時(shí)間?;蛘咭部梢匝舆t查詢邏輯放在前端,比如訂單支付完成后,可以前端延遲一秒再發(fā)起Ajax請(qǐng)求。
缺點(diǎn)是并不能數(shù)據(jù)保證完全準(zhǔn)確,如果數(shù)據(jù)同步延遲大于一秒則主從依舊不一致;另一個(gè)是造成接口響應(yīng)時(shí)間變長(zhǎng),甚至造成服務(wù)的吞吐量降低,對(duì)于不需要等待1s的場(chǎng)景,也必須等待夠1s。
判斷主備無(wú)延遲方案在構(gòu)建MySQL主從架構(gòu)的文章里提過(guò)一些關(guān)于主從搭建以及狀態(tài)查看的具體操作,具體請(qǐng)看下面這篇文章
快速入門Mycat及主從搭建指南
后文將要提到的關(guān)于判斷主備延遲的關(guān)鍵參數(shù)便是從 status 的結(jié)果中獲得的。
1.判斷Seconds_Behind_Master通過(guò) show slave status 可以拿到 Seconds_Behind_Master 的值,表示主備延遲的時(shí)間長(zhǎng)短。判斷 Seconds_Behind_Master 是否為 0,如果不等于0,就等到這個(gè)參數(shù)為0時(shí)再執(zhí)行查詢。但是這個(gè)延遲時(shí)間的單位為秒,所以可能產(chǎn)生一秒內(nèi)的誤差。
2.判斷同步binlog 位置在同步時(shí)通過(guò)文件名+文件位置就可以定位到binlog文件正在同步的位置。Master_Log_File和 Read_Master_Log_Pos,表示的是讀到的主庫(kù)的最新位點(diǎn);Relay_Master_Log_File和 Exec_Master_Log_Pos,表示的是備庫(kù)執(zhí)行的最新位點(diǎn)。
3.判斷GTID相同GITD在全局唯一,并且可以動(dòng)過(guò)GTID來(lái)定位binlog位置,所以也可以用來(lái)判斷主備是否有延遲
什么是GTID?
GTID特性是5.6加入的一個(gè)強(qiáng)大的特性,全稱是Global transaction Identifier。MySQL會(huì)為每一個(gè)DML/DDL操作增加一個(gè)唯一標(biāo)記叫做GTID,這個(gè)標(biāo)記在整個(gè)復(fù)制環(huán)境中都是唯一的。主從環(huán)境中主庫(kù)的DUMP線程可以直接通過(guò)GTID定位到需要發(fā)送的binary log位置,而不再需要指定binary log的文件名和位置,因此切換極為方便。關(guān)于DUMP線程是如何通過(guò)GTID定位到binary log位置的,我們將在第17節(jié)進(jìn)行討論。
Auto_Position=1 ,表示這對(duì)主備關(guān)系使用了 GTID 協(xié)議。Retrieved_Gtid_Set,是備庫(kù)收到的所有日志的 GTID 集合;Executed_Gtid_Set,是備庫(kù)所有已經(jīng)執(zhí)行完成的 GTID 集合。對(duì)比這兩個(gè)集合對(duì)應(yīng)的GTID相同就表示主備之間無(wú)延遲。
但是需要說(shuō)明的是,這里的無(wú)延遲,指的其實(shí)是從庫(kù)收到主庫(kù)的數(shù)據(jù)已經(jīng)全部執(zhí)行結(jié)束。但可能有種情況,客戶端已經(jīng)收到數(shù)據(jù),而對(duì)應(yīng)的binlog并沒(méi)有收到,這種情況下從庫(kù)是不知道的。
如何解決這個(gè)問(wèn)題呢?我們現(xiàn)在的困境是不知道主庫(kù)到底有沒(méi)有新執(zhí)行的數(shù)據(jù),從庫(kù)有沒(méi)有把最新binlog收到并且執(zhí)行,那如果主庫(kù)執(zhí)行完SQL我就拿到最新binlog位點(diǎn)呢?還有另一種思路,之所以產(chǎn)生這種情況,是因?yàn)?.7版本mysql默認(rèn)采用了異步復(fù)制的方式。如果想要數(shù)據(jù)更精確,就有必要在復(fù)制方式上做出改變。
對(duì)于這兩種思路又產(chǎn)生了后面幾種解決方案。
從庫(kù)等指定位點(diǎn)或GTID方案對(duì)于前面提到的思路,剛好MySQL有這樣一個(gè)命令。
select master_pos_wait(file, pos[, timeout]);
這條命令是在從庫(kù)執(zhí)行的,參數(shù) file 和 pos 指的是主庫(kù)上的文件名和位置,timeout 可選,設(shè)置為正整數(shù) N 表示這個(gè)函數(shù)最多等待 N 秒。這個(gè)命令正常返回的結(jié)果是一個(gè)正整數(shù) M,表示從命令開(kāi)始執(zhí)行,到應(yīng)用完 file 和 pos 表示的 binlog 位置,執(zhí)行了多少事務(wù)。
這樣就產(chǎn)生了一個(gè)方案。
主庫(kù)事務(wù)更新完成后,馬上執(zhí)行 show master status 得到當(dāng)前主庫(kù)執(zhí)行到的 File 和 Position。選定一個(gè)從庫(kù)執(zhí)行查詢語(yǔ)句。在從庫(kù)上執(zhí)行 select master_pos_wait(File, Position, 1)。如果返回值是 >=0 的正整數(shù),則在這個(gè)從庫(kù)執(zhí)行查詢語(yǔ)句,否則,到主庫(kù)執(zhí)行查詢語(yǔ)句。同樣的對(duì)于判斷位點(diǎn),可有一套判斷GTID的方案。
select wait_for_executed_gtid_set(gtid_set, 1);
邏輯與前者相同,只需要等待GTID到指定數(shù)字即可,這里大家舉一反三,不做贅述。
復(fù)制方式下面就開(kāi)始介紹關(guān)于復(fù)制方式方面的思路,從這些復(fù)制方式中,你會(huì)找到關(guān)于解決主備延遲問(wèn)題的更優(yōu)思路。先介紹一下異步復(fù)制模式。
異步復(fù)制異步模式就是客戶端提交 COMMIT 之后不需要等從庫(kù)返回任何結(jié)果,而是直接將結(jié)果返回給客戶端,這樣做的好處是不會(huì)影響主庫(kù)寫的效率,但可能會(huì)存在主庫(kù)宕機(jī),而 Binlog 還沒(méi)有同步到從庫(kù)的情況,也就是此時(shí)的主庫(kù)和從庫(kù)數(shù)據(jù)不一致。這時(shí)候從從庫(kù)中選擇一個(gè)作為新主,那么新主則可能缺少原來(lái)主服務(wù)器中已提交的事務(wù)。所以,這種復(fù)制模式下的數(shù)據(jù)一致性是最弱的。
默認(rèn)情況下,MySQL就是異步復(fù)制的模式。
半同步復(fù)制(增強(qiáng)半同步復(fù)制)在MySQL5.5中加入了半同步復(fù)制(semisynchronous replication),主庫(kù)上的事務(wù)在存儲(chǔ)引擎層提交之后,需要等待從庫(kù)返回ACK信號(hào)。并且在接收到從庫(kù)返回ACK信號(hào)或者等待超時(shí)才會(huì)返回給客戶端一個(gè)提交結(jié)果。但是這樣會(huì)造成其他會(huì)話可以讀取到這些記錄,因?yàn)榇藭r(shí)事務(wù)已經(jīng)提交,這就造成了幻讀。
在MySQL5.7中進(jìn)一步對(duì)半同步復(fù)制做了增強(qiáng),將等待從庫(kù)返回ACK信號(hào)的時(shí)間點(diǎn)提前了,新特性中主庫(kù)上的事務(wù)會(huì)在存儲(chǔ)引擎層提交之前一直等待從庫(kù)返回ACK信號(hào)。這就意味著,在主庫(kù)crash的情況下,所有在主庫(kù)上已經(jīng)提交的事務(wù)已經(jīng)被復(fù)制到至少一個(gè)從庫(kù)上,這就解決了幻讀的問(wèn)題,數(shù)據(jù)的一致性獲得了極大提升。
但是缺點(diǎn)也很明顯,會(huì)造成同步過(guò)程多了一次網(wǎng)絡(luò)連接,降低主庫(kù)的寫吞吐量。在 MySQL5.7 版本中還增加了rpl_semi_sync_master_wait_for_slave_count參數(shù) ,可以對(duì)從庫(kù)的應(yīng)答數(shù)量進(jìn)行設(shè)置,默認(rèn)為 1,也就是說(shuō)只要有 1 個(gè)從庫(kù)進(jìn)行了響應(yīng),就可以返回給客戶端。在1主1從情況下,這接近同步復(fù)制,如果使用semi-sync+位點(diǎn)判斷方案,這樣我們前面提到的主從數(shù)據(jù)不一致問(wèn)題引刃而解,但是如果多從還是有可能出現(xiàn)不一致的情況。
MGR 組復(fù)制MySQL在5.7.17 版本中引入了組復(fù)制技術(shù),簡(jiǎn)稱 MGR(MySQL Group Replication),這種復(fù)制技術(shù)是基于 分布式一致性協(xié)議Paxos 協(xié)議的,實(shí)現(xiàn)了分布式下數(shù)據(jù)的最終一致性。
A transaction received by Source 1 is executed. Source 1 then sends a message to the replication group, consisting of itself, Source 2, and Source 3. When all three members have reached consensus, they certify the transaction. Source 1 then writes the transaction to its binary log, commits it, and sends a response to the client application. Sources 2 and 3 write the transaction to their relay logs, then apply it, write it to the binary log, and commit it.
MGR 由若干個(gè)節(jié)點(diǎn)共同組成一個(gè)復(fù)制組,一個(gè)寫事務(wù)的提交,必須經(jīng)過(guò)組內(nèi)大多數(shù)節(jié)點(diǎn)(N / 2 + 1)決議并通過(guò),才能得以提交。如上圖所示,由3個(gè)節(jié)點(diǎn)組成一個(gè)復(fù)制組,Consensus層為一致性協(xié)議層,在事務(wù)提交過(guò)程中,發(fā)生組間通訊,由2個(gè)節(jié)點(diǎn)決議(certify)通過(guò)這個(gè)事務(wù),事務(wù)才能夠最終得以提交并響應(yīng),其實(shí)就是過(guò)半投票。
而針對(duì)只讀(RO)事務(wù)則不需要經(jīng)過(guò)組內(nèi)同意,直接 COMMIT 即可。在一個(gè)復(fù)制組內(nèi)有多個(gè)節(jié)點(diǎn)組成,它們各自維護(hù)了自己的數(shù)據(jù)副本,并且在一致性協(xié)議層實(shí)現(xiàn)了原子消息和全局有序消息,從而保證組內(nèi)數(shù)據(jù)的一致性。雖然半同步復(fù)制部分解決了一致性問(wèn)題,但只能在簡(jiǎn)單架構(gòu)下比如一主一從,MGR才真正解決了這個(gè)問(wèn)題,并且MGR可以在多主的復(fù)雜情況下有效保證數(shù)據(jù)的一致性。
總結(jié)總結(jié)一下,解決主從復(fù)制延遲一共可以有如下7種思路:
讀寫走主庫(kù)方案延遲查詢方案判斷主備無(wú)延遲方案判斷同步位點(diǎn)方案等待同步位點(diǎn)方案半同步復(fù)制方案+等待位點(diǎn)組復(fù)制MGR方案其實(shí)在實(shí)際生產(chǎn)中,這些方案是可以混合使用的,因?yàn)橐恢滦栽綇?qiáng)就意味著性能越低。比如業(yè)務(wù)不在乎是否查詢到過(guò)期數(shù)據(jù)就可以直接查詢從庫(kù),如果需要的一致性強(qiáng)可以選擇后幾種方案。
以上就是關(guān)于pos機(jī)數(shù)據(jù)超時(shí),MySQL主從數(shù)據(jù)不一致的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)數(shù)據(jù)超時(shí)的知識(shí),希望能夠幫助到大家!
