訪問日志IO性能優化
在高并發量的場景下磁盤IO往往是性能的瓶頸所在,訪問日志涉及到頻繁的寫操作,所以這部分要盡可能地優化,不然將拖累系統的整體性能。針對文件記錄及數據庫記錄兩種方式可以有以下措施提高寫性能,
l 避免頻繁的打開關閉文件。將日志寫入文件的一般操作步驟是打開-寫入-關閉,但假如在需要頻繁寫入日志的場景下,這種方式在性能上肯定會存在問題,因為每次打開關閉都是需要成本開銷的,所以必須要想想是否有別的更好的方式,竟然問題出現在打開關閉的次數,那么解決問題思路就從這里下手,可以在第一次打開寫入日志后不進行關閉操作,保持打開的狀態,下一次寫入則無需再次打開可直接寫入。而由于實際過程中訪問日志產生的量非常大,肯定不可能只往一個文件中寫入數據,可能會按時間間隔每天寫一個文件或按文件大小每50M寫一個文件,所以在實際設計中會涉及到更換文件的操作,更換時需要把原來的文件流關閉。通過上述措施避免了文件頻繁的打開關閉操作,但它同時也存在一些缺點,文件流不關閉會一直占用操作系統資源,且如果不及時關閉可能在程序運行過程中發生異常未正確處理而導致文件流未能關閉,進而將會導致內存泄漏。
l 添加緩沖區:添加緩沖區的作用簡單地說應該是減少文件真實寫入磁盤的次數,一般將文件寫入的方式是每執行一次寫入操作就把此次需要寫入的數據寫入磁盤介質中,而緩沖區模式則是把要寫入的數據先寫入內存中,當緩沖區內存量達到一定程度才寫入磁盤,所以添加了緩沖區的文件操作并非每次寫入都是存儲介質中,緩沖區對于IO操作是一個十分重要的概念,緩沖區具體的實現可以參考我前面相關的章節,當然jdk已經提供了相關的緩沖類并不用我們重復制造輪子。緩沖區的添加無疑提高了操作性能,但它同樣存在缺點,它無法百分之百保證所有數據都成功記錄到存儲介質中,可能在系統發生意外時導致緩沖區無法寫入文件,而丟失的僅僅是緩沖區的數據。
l 利用“池”技術優化連接避免每次創建連接,池技術更多的是針對以數據庫做為存儲端的方案,即是我們最熟悉的連接池了,JDBC每次創建連接都需要很大的成本開銷,如果每次寫入都重新建立連接這對系統來說簡直無法忍受,于是可以在系統初始化時就創建一個連接池,池內包含了很多建立好的連接,每次使用時只需往池里取出,使用完不關閉連接而是把連接重新放回池里即可。此種方式的好處顯而易見,操作性能大大地提高,而如果真要說有哪些缺點的話估計只能說連接池需要占用一些操作系統資源,即使沒有被使用。但對于現在的機器這點成本消耗基本可以忽略不計。
l 優化鎖競爭,首先,在一個高并發的場景中日志的寫入肯定是多線程的,多線程的使用在提高系統性能的作用是毋庸置疑的;其次,竟然在文件流的寫入操作是多線程的,那必然涉及到鎖競爭的問題,因為如果沒有鎖的保護文件可能被寫得亂七八糟且正確性無法得到保證,所以線程一定是在寫入前先嘗試競爭寫入鎖,只有成功獲取鎖的線程才能執行寫入操作,一旦寫完就釋放鎖;最后,這種鎖的競爭跟JDK的實現及JVM的實現相關,可能是所有競爭的線程采用自旋方式獲取鎖,也可能是采用線程掛起方式,對于自旋方式及掛起方式在不同場景有各自的優勢,線程自旋模式可能會消耗資源,同樣掛起恢復也可能會消耗資源,在實際使用中可通過性能測試比較決定使用哪種方式。在JDK的自帶的并發包是先嘗試自旋獲取,若干次失敗后進行掛起操作。
l 考慮使用非阻塞模式,所謂非阻塞(NIO)是指在進行IO操作時當執行寫入操作時不等待執行結果而是直接放棄對CPU的使用,這種模式基于事件驅動,不同的事件由某一或若干線程處理,在實際中NIO模式被證實在某些場景中是性能提升的利器。它的唯一缺點估計是讓你程序變得更加復雜。
使用異步IO,異步IO(AIO)是JDK1.7后提供的一種新IO模式,它主要是針對CPU的優化,是CPU級別的優化嘗試,在實際中使用需要對系統使用場景做性能測試對比再決定是否進行AIO改造。
來自:http://blog.csdn.net/wangyangzhizhou/article/details/46581991