針對innodb_flush_method參數的理解和對比測試(mycat+mysql)

    mysql的innodb_flush_method這個參數控制着innodb數據文件及redo log的打開、刷寫模式,對於這個參數,文檔上是這樣描述的:
有三個值:fdatasync(默認),O_DSYNC,O_DIRECT
默認是fdatasync,調用fsync()去刷數據文件與redo log的buffer
爲O_DSYNC時,innodb會使用O_SYNC方式打開和刷寫redo log,使用fsync()刷寫數據文件
爲O_DIRECT時,innodb使用O_DIRECT打開數據文件,使用fsync()刷寫數據文件跟redo log

首先文件的寫操作包括三步:open,write,flush
上面最常提到的fsync(int fd)函數,該函數作用是flush時將與fd文件描述符所指文件有關的buffer刷寫到磁盤,並且flush完元數據信息(比如修改日期、創建日期等)纔算flush成功。
使用O_DSYNC方式打開redo文件表示當write日誌時,數據都write到磁盤,並且元數據也需要更新,才返回成功。
O_DIRECT則表示我們的write操作是從MySQL innodb buffer裏直接向磁盤上寫。

這三種模式寫數據方式具體如下:

fdatasync模式:寫數據時,write這一步並不需要真正寫到磁盤纔算完成(可能寫入到操作系統buffer中就會返回完成),真正完成是flush操作,buffer交給操作系統去flush,並且文件的元數據信息也都需要更新到磁盤。
O_DSYNC模式:寫日誌操作是在write這步完成,而數據文件的寫入是在flush這步通過fsync完成
O_DIRECT模式:數據文件的寫入操作是直接從mysql innodb buffer到磁盤的,並不用通過操作系統的緩衝,而真正的完成也是在flush這步,日誌還是要經過OS緩衝

分別對這個三類模式進行對比測試:

一、測試條件

1、1000併發測試單表的增、刪、改、查操作,測試表已經設置索引,基礎數據量是一千五百多萬條(未做分表分庫)

2、測試環境:haproxy+2個mycat節點+3臺mysql(第一臺mysql爲主節點,負責寫,另外兩臺負責讀)

mysql服務器配置:8G內存,8核1.80Ghz CPU

3、mysql優化後配置參數:

max_connections=2000
innodb_buffer_pool_size=4G
join_buffer_size=1M
sort_buffer_size=1M
thread_cache_size=8
innodb_buffer_pool_instances=8
innodb_page_cleaners=4
innodb_purge_threads=1 #使用單獨的清除線程定期回收無用數據的操作
innodb_max_dirty_pages_pct=90 #innodb主線程刷新緩存池中的數據,使髒數據比例小於90%
wait_timeout=300
###從節點增加如下配置
innodb_doublewrite=off
innodb_page_cleaners=8
innodb_read_io_threads=64
innodb_write_io_threads=64
read_buffer_size=1M

二、測試結果

1、datasync(默認),O_DSYNC這兩種模式的磁盤IO比較高(只截取主節點mysql的監控圖,因爲兩個從節點通過主節點同步數據,IO壓力基本一致)

2、O_DIRECT模式的磁盤IO明顯低了好多

這說明O_DIRECT模式是將數據直接從MySQL innodb buffer向磁盤寫入,其寫入磁盤的速度應該是會低於從操作系統buffer往磁盤寫。

3、datasync(默認),O_DSYNC這兩種模式的free內存下降很快(特別是datasync模式)

通過linux中查看,free內存減少,相應的cache就會增多,這與大量將數據寫入到操作系統buffer中有關。

同時對比序號1中的磁盤IO變化情況圖就發現,free內存越少,IO就越大,這與頁交換頻繁相符合(頁換出越大,磁盤寫入的壓力越大):

4、O_DIRECT模式的free內存下降比較慢

5、對比其他測試結果如下:

從對比數據可以看出,O_DSYNC對CPU的壓力最大,datasync次之,O_DIRECT最小;整體SQL語句處理性能和響應時間看,O_DSYNC都較差;O_DIRECT在SQL吞吐能力上較好(僅次於datasync模式),但響應時間卻是最長的。

三、初步結論

終上結果做出分析如下:

(1)在類unix操作系統中,文件的打開方式爲O_DIRECT會最小化緩衝對io的影響,該文件的io是直接在用戶空間的buffer上操作的,並且io操作是同步的,因此不管是read()系統調用還是write()系統調用,數據都保證是從磁盤上讀取的;所以IO方面壓力最小,對於CPU處理壓力上也最小,對物理內存的佔用也最小;但是由於沒有操作系統緩衝的作用,對於數據寫入磁盤的速度會降低明顯(表現爲寫入響應時間的拉長),但不會明顯造成整體SQL請求量的降低(這有賴於足夠大的innodb_buffer_pool_size)。

(2)O_DSYNC方式表示以同步io的方式打開文件,任何寫操作都將阻塞到數據寫入物理磁盤後才返回。這就造成CPU等待加長,SQL請求吞吐能力降低,insert時間拉長。

(3)fsync(int filedes)函數只對由文件描述符filedes指定的單一文件起作用,並且等待寫磁盤操作結束,然後返回。fdatasync(int filedes)函數類似於fsync,但它隻影響文件的數據部分。而除數據外,fsync還會同步更新文件的元信息到磁盤。

 默認datasync模式,整體表現較好,因爲充分利用了操作系統buffer和innodb_buffer_pool的處理性能,但帶來的負面效果是free內存降低過快,最後導致頁交換頻繁,磁盤IO壓力大,這會嚴重影響大併發量數據寫入的穩定性。也就是說擁有了高性能,但不會有高穩定性(特別是mycat集羣,在大量數據寫入和各節點mysql數據同步壓力下,IO是很大的)。爲了解決這個問題,可以有個折中的辦法,定時的對操作系統進行echo 3 >/proc/sys/vm/drop_caches,清理一下OS緩存,可以及時回收一部分內存(回收順間對性能會有所影響)。

O_DIRECT模式網上一些評論認爲是性能最好的,但本次測試的結果來看,性能並不是很高,但是穩定性確實比較高,在大併發量讀寫操作中,能夠較長時間運行,只是在第一次啓動系統後測試,該模式一開始的響應時間確實比較長,到後面才恢復到較低水平(分析的原因是因爲有兩個mysql節點變成寫模式了,可能重啓mysql出現讀寫狀態變化,在做這個測試時由於開發人員還配了Galera,兩節點同時寫入是基於row級的,所以開始很容易引起鎖,響應時間就變得很慢),如下所示:

 

總結:對於mycat讀寫分離中,寫數據壓力小,讀數據壓力大的情況下,並且內存夠大,innodb_buffer_pool_size配置夠大的情況下,其實三種模式應該都行,讀數據的性能基本是依賴於緩存,如果從穩定性和內存使用情況來考慮,用O_DIRECT模式會更好些,並通過優化查詢以彌補響應時間不夠快的問題。對於讀寫壓力都很大或只是寫的壓力大的情況下,建議用datasync模式,並配上定期清理系統緩存的機制。如果我們充分應用了mycat的分表分庫和讀寫分離機制,那麼對於整體系統的性能和穩定性都有幫助(因爲大庫和大表,都會嚴重降低數據的寫入和讀出性能,這樣的話光是靠innodb_flush_method的模式配置也是治標不治本)。

至於,生產環境如何設置一定要以壓測結果爲準,以實際效果爲準,不能盲目信任經驗值。

跟大家推薦一個學習資料分享羣:747981058,裏面大牛已經爲我們整理好了許多的學習資料,有自動化,接口,性能等等的學習資料!人生是一個逆水行舟的過程,不進則退,咱們一起加油吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章