- MySQL高可用實踐
- 王雪迎
- 1520字
- 2021-03-26 23:06:31
2.2 性能提升
MySQL一直致力于提升半同步復(fù)制的性能,從以下三個方面便可見:
(1)支持發(fā)送二進制日志事件和接收ACK的異步化。
(2)控制主庫接收確認(rèn)從庫的反饋數(shù)量。
(3)二進制日志互斥鎖的改進。
2.2.1 ACK異步化
舊版本的半同步復(fù)制受限于Binlog Dump線程,原因是該線程承擔(dān)了兩個不同且又十分頻繁的任務(wù):傳送二進制日志事件給從庫;接收從庫的ACK反饋信息。這兩個任務(wù)是串行的,Binlog Dump線程必須等待從庫返回之后才會傳送下一個事件。Binlog Dump線程已然成為整個半同步復(fù)制性能的瓶頸。在高并發(fā)業(yè)務(wù)場景下,這樣的機制會影響數(shù)據(jù)庫整體的吞吐量。單個Binlog Dump線程發(fā)送和接收的工作流程如圖2-1所示。

圖2-1 單個Binlog Dump線程發(fā)送和接收的工作流程
為了解決上述問題,在MySQL 5.7.4版本的半同步復(fù)制框架中,獨立出一個Ack Receiver線程,專門用于接收從庫返回的ACK請求,這將之前Binlog Dump線程的發(fā)送和接收工作分為了兩個線程來處理。這樣主庫上有兩個線程獨立工作,可以同時發(fā)送二進制日志事件到從庫,和接收從庫的ACK信息。因此半同步復(fù)制得到了極大的性能提升。Binlog Dump線程與Ack Receiver線程的工作流程如圖2-2所示。

圖2-2 Binlog Dump線程與Ack Receiver線程的工作流程
Ack Receiver線程在主庫啟用半同步復(fù)制時創(chuàng)建,并在主庫禁用半同步復(fù)制時銷毀,它是自動創(chuàng)建和銷毀的,因此不受用戶控制。它的狀態(tài)信息可以從performance_schema中查詢到:

Ack receiver線程有以下三個狀態(tài):
- Waiting for semi-sync slave connection
- Waiting for semi-sync ACK from slave
- Reading semi-sync ACK from slave
在MySQL 5.7.17之前,這個Ack Receiver線程采用了select機制來監(jiān)聽從庫返回的結(jié)果,然而select機制監(jiān)控的文件句柄只能是0~1024,當(dāng)超過1024時,用戶在MySQL的錯誤日志中會收到類似如下的報錯,更有甚者會導(dǎo)致MySQL發(fā)生宕機。
semi-sync master failed on net_flush() before waiting for slave reply.
從MySQL 5.7.17版本開始,官方修復(fù)了這個bug,開始使用poll機制來替換原來的select機制,從而可以避免上面的問題。其實poll調(diào)用本質(zhì)上和select沒有區(qū)別,只是I/O句柄數(shù)理論上沒有了上限,因為它是基于鏈表來存儲的。
2.2.2 控制從庫反饋的數(shù)量
MySQL 5.7新增了rpl_semi_sync_master_wait_for_slave_count系統(tǒng)變量,可以用來控制主庫接收多少個從庫寫事務(wù)成功后的反饋,給高可用架構(gòu)切換提供了靈活性。如圖2-3所示,當(dāng)該變量值為2時,主庫需等待兩個從庫的ACK。

圖2-3 “一主兩從”的半同步復(fù)制
使用這個功能,可以在不同機房部署主服務(wù)器和兩個從服務(wù)器,并配置半同步復(fù)制以將事務(wù)復(fù)制到至少兩個從庫,以便在多個服務(wù)器一次性崩潰的情況下減少數(shù)據(jù)丟失的可能,從庫越多,數(shù)據(jù)越安全。
2.2.3 二進制日志互斥鎖的改進
舊版本半同步復(fù)制在主庫提交二進制日志的寫會話和Binlog Dump線程讀取二進制日志的操作時,都會對二進制日志添加binlog lock互斥鎖,用于保護二進制日志的讀寫安全。使用此互斥鎖,二進制日志讀寫操作是安全的,但會導(dǎo)致二進制日志文件的讀寫串行化。不僅Binlog Dump線程和用戶會話不能同時讀寫二進制日志,就連多個Binlog Dump線程本身也無法同時讀寫。每當(dāng)一個會話正在讀取或?qū)懭攵M制日志文件時,所有其他會話都必須等待。如此順序讀寫是一個瓶頸,尤其是當(dāng)讀寫操作很慢時。串行化讀寫二進制日志如圖2-4所示。

圖2-4 串行化讀寫二進制日志
MySQL 5.7.2對binlog lock進行了以下兩方面的優(yōu)化:
- 從Binlog Dump線程中移除binlog lock。
- 加入了安全邊際以保證二進制日志的讀安全。
二進制日志文件是一個僅用于追加二進制事件的日志文件,可以安全地從中讀取沒有鎖定的二進制事件,因此可以從Binlog Dump線程中刪除binlog鎖。不使用binlog鎖,而是為活動binlog維護安全讀取邊界(最大位置)。Binlog Dump線程永遠不會讀取超過安全讀取的邊界。當(dāng)?shù)竭_邊界時,它將等待邊界更新。用戶會話負責(zé)在追加了二進制事件后更新安全讀取邊界。改進后的二進制日志讀寫如圖2-5所示。

圖2-5 改進后的二進制日志讀寫
從圖2-5中一目了然:
- 讀取二進制日志事件時,Binlog Dump線程不會相互阻塞。
- 正在寫二進制日志事件的用戶會話不會阻止Binlog Dump線程。
- 讀取二進制日志事件的Binlog Dump不會阻塞用戶會話。
因此,Binlog Dump線程和用戶會話都可以獲得更好的吞吐量,尤其是在有很多從庫時,這種改進非常顯著。
- 大學(xué)計算機基礎(chǔ)(第二版)
- Apache Spark 2.x Machine Learning Cookbook
- Software Testing using Visual Studio 2012
- Python數(shù)據(jù)分析(第2版)
- Java EE 7 Development with NetBeans 8
- Mastering ServiceNow(Second Edition)
- R大數(shù)據(jù)分析實用指南
- Raspberry Pi Home Automation with Arduino(Second Edition)
- PySpark Cookbook
- 微服務(wù)從小白到專家:Spring Cloud和Kubernetes實戰(zhàn)
- Mastering C++ Multithreading
- 計算機應(yīng)用基礎(chǔ)教程(Windows 7+Office 2010)
- Building Dynamics CRM 2015 Dashboards with Power BI
- Getting Started with Python
- Learning Android Application Testing