最近對同機房semisync性能優化告一段落,性能基本能達到預期;目前優化的版本基于mysql5.6.14,基本優化思路是讓備庫盡快的發送ack。主要的優化點簡單總結下:
a).備庫在接受到需要ack的事件時,先ack,再去寫relay log。對于不需要ack的事件隻寫io cache
原始行為為每接受到一個事件就寫一次relay log,在同機房場景下,可能存在網絡io已經完成,備庫還沒寫完資料到磁盤
b).備庫在需要ack時才去刷master info檔案
原始行為是每接受一個事件寫一次master_info檔案
a)和b)以犧牲備庫日志的持久化來提升semisync場景下的主庫性能,當備庫挂了時,隻需要從一個安全的位點重拉binlog即可;
使用sysbench測試的結果:tps 13000(原生semisync) => 24000 (改進後semisync)
無semisync的tps約為28000
上述測試同時基于以下的改進
c).主庫上在事務commit之前等待備庫ack(after_sync),在等待期間其他事務無法看到等待線程所做的修改,如果主庫挂了,切換到備庫後,應用連接配接隻需要檢查資料是否更新成功即可 (port from mysql5.7.2)
原始行為為在事務commit之後(after_commit),每個應用連接配接等待備庫ack,這種情況下在主備切換後,應用連接配接将無法判斷其事務是否成功送出(資料可能被修改多次)
after_sync比after_commit更能保證資料的一緻性,并且有一定的性能提升,因為在after_sync發生在innodb group commit之前,由leader線程來等待,隻需要喚醒leader,而after_commit在大thread running下,可能需要喚醒大量應用連接配接,開銷更大
d).mysql_binlog_send函數不再需要持有lock_log鎖來讀取binlog事件,而是維持一個檔案末尾的偏移量;(port from mysql5.7.2, facebook mysql5.6有類似實作)
原始行為中,寫binlog和讀binlog都需要lock_log這個大鎖來保護,這會導緻鎖競争,如果有多個備庫dump線程,這種競争會影響到tps
e).在rotate時,需要生成下一個binlog檔案,在設定檔案名字尾時,避免掃描整個檔案夾,改為維護一個遞增數字
其他一些小的修改點不一一列出;
semisync接下來潛在的優化點:
a).大量dump線程對主庫性能的影響需要納入考慮(例如bug#70342)
b).如何保證主備庫的強一緻;例如,主庫當機,事務已寫入本地binlog,但還沒發送到備庫;主備切換後,如果應用連結在備庫重試事務,則主備一緻;如果應用抛棄該事務,或走其他邏輯,那麼挂掉重新開機後的主庫可能比備庫多執行了事務(利用adha復原機制?)
c).在跨機房場景下,網絡稱為瓶頸時,如何解決(并發網絡io?)
d).内建semisync,而不是通過plugin的形式,是否可能帶來性能提升?
e).主庫semisync 的大鎖對性能的影響?