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