存储方式与介质对性能的影响
摘要
數據的存儲方式對應用程序的整體性能有著極大的影響。對數據的存取,是順利讀寫還是隨機讀寫?將數據放磁盤上還將數據放flash卡上?多線程讀寫對性能影響?面對著多種數據存儲方式,我們如何選擇?本文給大家提供了一份不同存儲模式下的性能測試數據,方便大家在今后的程序開發過程中可以利用這份數據選擇合適的數據存儲模式。
TAG
存儲性能,innodb性能,存儲介質
目錄
目錄… 1
簡介… 1
存儲性能分析… 2
測試程序說明:… 2
存儲測試數據:… 2
Mysql innodb性能測試… 4
Mysql(InnoDB)刷盤策略… 6
c/s模式通信性能… 6
直接文件存儲… 7
文件IO方式… 7
完全隨機寫還是跳躍,5倍的性能差距… 8
多線程隨機讀、處理速度、響應時間… 9
系統緩存… 10
系統緩存相關的幾個內核參數… 10
dirty頁的write back. 10
總結… 11
簡介
數據的存儲方式對應用程序的整體性能有著極大的影響。對數據的存取,是順利讀寫還是隨機讀寫?將數據放磁盤上還將數據放flash卡上?多線程讀寫對性能影響?面對著多種數據存儲方式,我們如何選擇?
本文會對不同存儲方式做詳細的性能測試,以提供給大家一份不同存儲方式下的性能測試數據為主,同時會簡單介紹各種存儲方式之間的性能差異。
存儲性能分析
影響儲存速度有各個方面的原因,包括存儲介質、讀寫盤方式以及硬件環境對讀寫盤時的影響。這里主要分享存儲速度的一些調研結果。
硬件環境如下:
CPU:????? INTER Nehalem E5620 2.4GHZx2
內存:???? PC-8500 4GB*8
硬盤:???? 300G 10k*2, RAID:1
Flash:??? SSD 160GB_MLC X25-M G2×6
網卡:???? 千兆
數據量:117G
測試程序說明:
測試共分兩套程序:
- A. 存儲測試
a)???????? 存儲測試程序均使用pread/pwrite進行存儲測試,塊鏈遍歷速度采用frs開發的塊鏈庫進行。
b)???????? 為了減少隨機讀寫時系統緩存帶來的影響
i.????????????? 將數據量增大至117G
ii.???????????? 每次數據只被測試一次
iii.????????????程序入口處清內存
c)???????? 測順序讀寫時,一次讀寫所有數據。
d)???????? 測隨機讀寫時,每次讀4KB,讀381MB。
- B. 網絡性能測試
a)???????? 采用ub + ubrpc實現壓力工具的服務器端和客戶端。
b)???????? UBSVR_NODELAY
c)???????? 常用的Idl規范
d)???????? 對兩個不同大小的包請求進行測試
存儲測試數據:
磁盤
順序讀:145.59MB/s
隨機讀:0.91MB/s? (每次讀4KB,讀381MB)
順序寫:83.1MB/s
隨機寫:0.34MB/s? (每次寫4KB,? 寫381MB)
Flash
順序讀:61.5MB/s
隨機讀:14.9MB/s? (每次讀4KB,讀381MB)
順序寫:59.8MB/s
隨機寫:1.93MB/s? (每次寫4KB,? 寫381MB)
內存
順序寫:1655MB/s
隨機寫:1496MB/s
Eg: 塊鏈遍歷速度1000萬元素, 565582 us
磁盤與flash卡的順序讀寫性能對比(單位MB):
磁盤與flash卡的隨機讀寫性能對比(單位MB):
對比磁盤和flash卡的隨機讀寫性能,我們可以看到:對于寫操作而言,其在磁盤和flash卡上的性能差異較小,且事實上其性能差異會隨著隨機寫時每次寫入的數據量以及flash卡塊大小等其它因素而產生波動;同時,在帶寫優化的flash上,當將數據寫入flash卡時,數據會先寫到一塊buffer中,當滿足一定條件(如buffer滿)后,會將buffer的數據刷入flash,此時會阻塞寫,因此會帶來性能抖動。所以,當應用程序的多數操作是寫入操作時,若沒有flash卡也可以勉強將數據放到磁盤上。
但是相反,從測試結果看,在磁盤和flash卡上的隨機讀性能有著8倍甚至更多的差距,所以當程序讀磁盤操作相當多時,把數據放到flash卡上是一個比較好的選擇。比如,對于一個隨機查詢較多數據庫應用程序,我們可以考慮把數據庫的存儲文件放到flash卡上。
另一方面,我們可以直觀地看到,無論順序讀還是順序寫,在磁盤上的速度都遠遠高于在flash卡上的速度。所以如果程序所需的數據是從磁盤一次載入,載入后對數據的修改都是內存操作,不直接寫盤,當需要寫盤時,也是一次將內存中的數據dump到磁盤上時。我們都應該將數據放到磁盤,而不是flash卡上。
Mysql innodb性能測試
Mysql測試一:存讀
硬盤環境與配置:
innodb_buffer_pool_size = 5120M
innodb_flush_log_at_trx_commit = 0
機器內存:32G
cpu:4核 Intel(R) Xeon(R) CPU??????????? 5150? @ 2.66GHz
flash:256G,slc 沒有寫優化,沒有raid。
壓力:
mysqlab args:-uroot -proot -h127.0.0.1 -P3306 -dfrs -fr.sql -c1 –t40 -s1000
50個線程,每個線程1000req/s的壓力:
結論:
| 每秒處理次數 | 4700左右。 |
| max響應時間 | 139374 us |
| 平均響應時間 | 8535us |
| ? | ? |
iostat:
從系統狀態來看,
flash性能已經到極限。
Mysql測試二:讀寫沖突測試
| 讀壓力 | 真實壓力 | 寫壓力 | 真實寫壓力 |
| 0 | 0 | 單線程1000 | 300左右(起初很快,但最終會降下來) |
| 0 | 0 | 10線程*1000 | 300左右(起初很快,但會降下來,降下來后,很不穩定) |
| 40線程*80 | 2000上下浮動 | 單線程300 | 平均60+ |
| 40線程*50 | 1000+上下浮動 | 單線程300 | 平均80+ |
| 40線程*40 | 1500 | 單線程100 | 80+ |
可見,flash讀寫沖突非常嚴重,如果壓力太高,會導致被壓垮,反而在寫壓力恒定在100次的時候,可以支持1500以上的并發讀請求,且比較穩定。
線上,最還還是使用寫優化的mlc。以減少讀寫沖突。
Mysql測試三:mlc+寫優化flash
只有讀的情況:
| 讀壓力 | 真實讀壓力 | 寫壓力 | 真實寫壓力 |
| 40線程*1000 | 8300+ | 0 | 0 |
| 40線程*80 | 2900 | 單線程*200 | 160-190 |
| 40線程*125 | 4000+ | 單線程*200 | 160~190 |
可見,mlc+寫優化后,比slc在性能上有較大提升。
可以支持4000次讀+160以上的寫請求。
Mysql(InnoDB)刷盤策略
上面做了Mysql InnDB的一些性能測試,這里講一下InnoDB的刷盤策略。InnoDB存儲引擎會有一個緩沖池(緩沖池的大小可根據配置來修改innodb_buffer_pool_size),InnoDB在讀數據庫文件的數據時,會先將數據庫文件按頁讀取這個buffer,然后按LRU的算法來保留緩沖池中的數據。當需要修改數據時,會先修改buffer里面的數據,此時buffer里的數據可能為臟數據,然后InnoDB會按一定的頻率將緩沖池里的臟頁刷新到文件。
對于刷臟頁的時機和數量,Innodb會根據當然系統的IO壓力等因素來決定是否刷盤。它會分每秒鐘觸發一次的刷盤和每10秒鐘觸發一次的刷盤。在每秒鐘觸發一次刷盤的條件是:當前緩沖池中臟頁的比例超過了配置文件中innodb_max_dirty_pages_pct這個參數。而在每10秒鐘觸發一次的刷盤中,InnoDB至少會刷10個臟頁(如果有的話)到磁盤,同時InnoDB引擎會判斷緩沖池中的臟頁的比例,如果超一定比例的話,會刷100個臟頁到磁盤。
c/s模式通信性能
在這一節,我們用百度的UB框寫了兩個網絡性能測試程序。主要測試數據包大小對網絡服務的影響,以及跨機房之間的網絡延遲數據。
程序&硬件:
網卡帶寬:1000Mb
通信協議:ubrpc
配置:長連接、EPOOL、server配40線程
同機房:
請求包大小:13000byte/pack
單線程壓: 1600/s, 網卡流量: 20.6Mb
8個線種壓:9000/s, 網卡流量: 122Mb? (基本達網卡極限)
請求包大小:1700byte/pack
單線程壓: 2900/s, 網卡流量: 4.7Mb
36個線種壓:穩定28000/s, 網卡流量: 50.3Mb? (此時對于千兆網卡來說,帶寬還非常充裕,但CPU r值已經在10左右。再往上壓服務器出現不穩定現象。
跨機房延遲: 817us
請求包大小:1700byte/pack
單線程壓: 860/s, 網卡流量: 1.4Mb
同樣的程序,單線程壓跨機房的性能明顯下降,不到同機房的1/3。每個請求延遲達817us
直接文件存儲
文件IO方式
直接文件存儲指將內存中的數據直接寫到磁盤上,我們通常用munmap、fwrite、pwrite和write等方式進行數據寫入。反之用mmap、fread、pread和read等方式從磁盤文件載入數據到內存中。
Mmap/munmap
1. mmap/munmap是一種內存映射技術,它用于把磁盤文件映射到內存中,對內存中數據的修改,會被映射回磁盤;Linux內核會維護一個數據結構,以建立虛擬地址空間的區域與相關數據之間的關聯。文件區間與它所映射到的地址空間的關聯是通過優先樹完成的,如圖(1.1)所示。Mmap技術無論從速度還是易用性上都有著非常不錯的表現。
圖1.1???????? struct file是指用open打開的一個文件句柄,其中f_mapping是包含一個指向inode和優先樹的address_space結構體的指針,用做內存映射。
pwrite/write
其次,先說一下pwrite和write,它們都屬于文件IO,數據流是從“進程=>fd=>文件”,都是直接調用系統調用的函數。兩者不同的是,pwrite相當于順序調用 lseek 和 write , 然后調用pread時,無法中斷其定位和讀操作,也就是說lseek和write相當于是原子操作;另外一點是pwrite不會更新文件的指針。
在多線程io操作中,對io的操作盡量使用pread和pwrite,否則,如果使用seek+write/read的方式的話,就需要在操作時加鎖。這種加鎖會直接造成多線程對同一個文件的操作在應用層就串行了。從而,多線程帶來的好處就被消除了。
使用pread方式,多線程也比單線程要快很多,可見pread系統調用并沒有因為同一個文件描述符而相互阻塞。pread和pwrite系統調用在底層實現中是如何做到相同的文件描述符而彼此之間不影響的?多線程比單線程的IOPS增高的主要因素在于調度算法。多線程做pread時相互未嚴重競爭是次要因素。
內核在執行pread的系統調用時并沒有使用inode的信號量,避免了一個線程讀文件時阻塞了其他線程;但是pwrite的系統調用會使用inode的信號量,多個線程會在inode信號量處產生競爭。pwrite僅將數據寫入cache就返回,時間非常短,所以競爭不會很強烈。
在使用pread/pwrite的前提下,如果各個讀寫線程使用各自的一套文件描述符,是否還能進一步提升io性能?
每個文件描述符對應內核中一個叫file的對象,而每個文件對應一個叫inode的對象。假設某個進程兩次打開同一個文件,得到了兩個文件描述符,那么在內核中對應的是兩個file對象,但只有一個inode對象。文件的讀寫操作最終由inode對象完成。所以,如果讀寫線程打開同一個文件的話,即使采用各自獨占的文件描述符,但最終都會作用到同一個inode對象上。因此不會提升IO性能。
pwrite/fwrite
最后,說一下pwrite/fwrite。雖然他們的功能都是將內存中的數據存入文件。但原理和過程都有所不同。剛剛說過pwrite是屬于文件IO,數據流是從“進程=>fd=>文件”,而fwrite是流/標準IO,其數據流是從“進程=>fp(FILE對象)=>流/緩沖=>文件”;原本直接對文件的操作,在fwrite庫函數中變為對流對象的操作,而“流=>文件”這一層的操作將由庫函數為我們完成。流的邏輯表示就是FILE對象,而流的實體就是流使用的緩沖區,這些緩沖區相對于應用進程來說就是文件的代表。
完全隨機寫還是跳躍,5倍的性能差距
全隨機寫無疑是最慢的寫入方式,在logic dump測試中很驚訝的發現,將200M的內存數據隨機的寫入到100G的磁盤數據里面,竟然要2個小時之多。原因就是雖然只有200M的數據,但實際上卻是200萬次隨機寫,根據測試,在2850機器上,這樣完全的隨機寫,r/s 大約在150~350之間,在180機器上,r/s難以達到250,這樣計算,難怪需要2~3個小時之久。
如何改進這種單線程隨機寫慢的問題呢。一種方法就是盡量將完全隨機寫變成有序的跳躍隨機寫。實現方式,可以是簡單的在內存中緩存一段時間,然后排序,使得在寫盤的時候,不是完全隨機的,而是使得磁盤磁頭的移動只向一個方向。根據測試,再一次讓我震驚,簡單的先在內存中排序,竟然直接使得寫盤時間縮短到1645秒,磁盤的r/s也因此提升到1000以上。寫盤的速度,一下子提高了5倍。
一個需要注意的地方,這種跳躍寫對性能的提升,來至與磁頭的單方向移動,它非常容易受其他因素的影響。測試中,上面提到的測試是只寫block文件,但如果在每個tid的處理中再增加一個寫index的小文件。雖然如果只寫index小文件,所用時間幾乎可以忽略,但如果夾雜在寫block文件中間的話,對整體的寫性能可能影響巨大,因為他可能使得磁盤的磁頭需要這兩個地方來回跑。根據測試,如果只寫index文件,只需要300s就可以寫完所有200萬個tid,單如果將寫索引和寫block放在一起,總時間就遠大于分別寫這兩部分的時間的和。針對這種情況,一種解決方案就是就不要將小數據量的數據實時的刷盤,使用應用層的cache來緩存小數據量的index,這樣就可以消除對寫block文件的影響。
從原理上解釋上面的表象,一般來說,硬盤讀取數據的過程是這樣的,首先是將磁頭移動到磁盤上數據所在的區域,然后才能進行讀取工作。磁頭移動的過程又可以分解為兩個步驟,其一是移動磁頭到指定的磁道,也就是尋道,這是一個在磁盤盤片徑向上移動的步驟,花費的時間被稱為“尋道時間”;其二就是旋轉盤片到相應扇區,花費的時間被稱為“潛伏時間”(也被稱為延遲)。那么也就是說在硬盤上讀取數據之前,做準備工作上需要花的時間主要就是“尋道時間”和“潛伏時間”的總和。真正的數據讀取時間,是由讀取數據大小和磁盤密度、磁盤轉速決定的固定值,在應用層沒有辦法改變,但應用層缺可以通過改變對磁盤的訪問模式來減少“尋道時間”和“潛伏時間”, 我們上面提到的在應用層使用cache然后排序的方式,無疑就是縮短了磁盤的尋址時間。由于磁頭是物理設備,也很容易理解,為什么中間插入對其他小文件的讀寫會導致速度變慢很多。
建議:盡量避免完全的隨機寫,在 不能使用多線處理的時候,盡量使用應用層cache,確保寫盤時盡量有順序性。對于小數據量的其他文件,可以一直保存在應用層cache里面,避免對其他大數據量的數據寫入產生影響。
多線程隨機讀、處理速度、響應時間
多線程隨機讀的處理速度可以達到單線程隨機讀的10倍以上,但同上也帶來了響應時間的增大。測試結論如下:(每個線程盡量讀)
| 讀線程數 | 讀出100次耗時(um) | 讀平均相應時間(um) |
| 1 | 1329574 | 13291 |
| 5 | 251765 | 12976 |
| 10 | 149206 | 15987 |
| 20 | 126755 | 25450 |
| 50 | 96595 | 48351 |
結論標明增加線程數,可以有效的提升程序整體的io處理速度。但同時,也使得每個io請求的響應時間上升很多。
從底層的實現上解釋這個現象:應用層的io請求在內核態會加入到io請求隊列里面。內核在處理io請求的時候,并不是簡單的先到先處理,而是根據磁盤的特性,使用某種電梯算法,在處理完一個io請求后,會優先處理最臨近的io請求。這樣可以有效的減少磁盤的尋道時間,從而提升了系統整體的io處理速度。但對于每一個io請求來看,由于可能需要在隊列里面等待,所以響應時間會有所提升。
響應時間上升,應該主要是由于我們測試的時候采用每個線程都盡量讀的方式。在實際的應用中,我們的程序都沒有達到這種壓力。所以,在io成為瓶頸的程序里面,應該盡量使用多線程并行處理不同的請求。對于線程數的選擇,還需要通過性能測試來衡量。
系統緩存
系統緩存相關的幾個內核參數
- /proc/sys/vm/dirty_background_ratio
該文件表示臟數據到達系統整體內存的百分比,此時觸發pdflush進程把臟數據寫回磁盤。
缺省設置:10 - /proc/sys/vm/dirty_expire_centisecs
該文件表示如果臟數據在內存中駐留時間超過該值,pdflush進程在下一次將把這些數據寫回磁盤。
缺省設置:3000(1/100秒) - /proc/sys/vm/dirty_ratio
該文件表示如果進程產生的臟數據到達系統整體內存的百分比,此時進程自行把臟數據寫回磁盤。
缺省設置:40 - /proc/sys/vm/dirty_writeback_centisecs
該文件表示pdflush進程周期性間隔多久把臟數據寫回磁盤。
缺省設置:500(1/100秒)
dirty頁的write back
系統通常會在下面三種情況下回寫dirty頁
- 定時方式: 定時回寫是基于這樣的原則:/proc/sys/vm/dirty_writeback_centisecs的值表示多長時間會啟動回寫線程,由這個定時器啟動的回寫線程只回寫在內存中為dirty時間超過(/proc/sys/vm/didirty_expire_centisecs / 100)秒的頁(這個值默認是3000,也就是30秒),一般情況下dirty_writeback_centisecs的值是500,也就是5秒,所以默認情況下系統會5秒鐘啟動一次回寫線程,把dirty時間超過30秒的頁回寫,要注意的是,這種方式啟動的回寫線程只回寫超時的dirty頁,不會回寫沒超時的dirty頁,可以通過修改/proc中的這兩個值,細節查看內核函數wb_kupdate。
- 內存不足的時候: 這時并不將所有的dirty頁寫到磁盤,而是每次寫大概1024個頁面,直到空閑頁面滿足需求為止
- 寫操作時發現臟頁超過一定比例: 當臟頁占系統內存的比例超過/proc/sys/vm/dirty_background_ratio 的時候,write系統調用會喚醒pdflush回寫dirty page,直到臟頁比例低于/proc/sys/vm/dirty_background_ratio,但write系統調用不會被阻塞,立即返回.當臟頁占系統內存的比例超/proc/sys/vm/dirty_ratio的時候, write系統調用會被被阻塞,主動回寫dirty page,直到臟頁比例低于/proc/sys/vm/dirty_ratio
總結
本文給大家提供了一份不同存儲模式下的性能測試數據,方便大家在今后的程序開發過程中可以利用這份數據選擇合適的數據存儲模式。同時講述了關于文件IO讀寫操作以及系統緩存層面的一些問題。
轉自:http://stblog.baidu-tech.com/?p=851
總結
以上是生活随笔為你收集整理的存储方式与介质对性能的影响的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哪里可以看免费的电影?
- 下一篇: 燕翎义薄云天观看地址