性能調優,程序員轉型架構師的攔路虎【3】

性能調優系列前序文章索引:html

  • 程序員必須掌握的性能調優老兵哥結合我的經歷解釋了程序員往架構師方向發展時爲何要跨越性能調優這一關,以及介紹了從 X、Y、Z 三個維度優化性能的思路。
  • 從  X  維度優化系統的性能老兵哥分享了從 X 維度優化系統性能的思路,包括讓客戶端分計算存儲任務、優化交互設計等,主要是做爲引子拓寬咱們性能調優的思路。
  • 應用容器 Tomcat 性能調優Y 維度就是從業務 HTTP 請求的橫向處理流程來看,HTTP 請求會穿越網絡、計算機、應用容器(Tomcat)、Spring、ORM(Hibernate)、數據庫等節點,在這個流程中每一個節點都有許多能夠可優化的地方,此文主要介紹經過優化應用容器(Tomcat)來優化系統性能的方法。

程序員在轉型架構師的過程當中須要創建流程化、結構化、系統化的思惟方式,而性能調優是很是可貴的契機,它既給了咱們壓力,也給了咱們動力,跨越它就是突破本身的過程。程序員

  • X 維度,即業務維度,技術始終是服務業務的,任何技術問題的原點就是業務需求。在啓動技術層面的性能優化以前,咱們有必要先審視一下業務流程是否合理,交互設計上有沒有能夠優化的空間等。
  • Y 維度,待業務維度優化完畢,接下來就是審視技術在實現當前業務流程或交互設計的全鏈路上有沒有可優化的地方,即 HTTP 請求處理全流程,從瀏覽器到應用容器,再到 Spring、Hibernate、數據庫等。
  • Z 維度,除了沿着 HTTP 請求的橫向鏈路,咱們還要審視支持應用系統的縱向技術棧,從上到下包括 JVM、操做系統和硬件等,這是整套應用系統運行的環境,許多性能問題都跟運行環境存在關係。

今天老兵哥將介紹經過優化開發框架 Spring 來優化系統性能的方法。數據庫

3. 開發框架 Spring瀏覽器

3.1 事務管理緩存

事務(Transaction),是併發控制的基本單位,是用戶定義的一個操做序列。這些操做要麼都作,要麼都不作,是一個不可分割的工做單位。經過使用事務控制,咱們能夠極大地避免邏輯處理失敗致使的髒數據等問題。事務具備 4 個屬性:原子性、一致性、隔離性、持久性等,這四個屬性一般稱爲 ACID 特性。安全

  • 原子性(Atomicity),一個事務是一個不可分割的工做單位,事務包含的操做要麼都作、要麼都不作。
  • 一致性(Consistency),事務必須讓數據庫從一個一致性狀態變到另外一個一致性狀態,不能出現不一致。
  • 隔離性(Isolation),一個事務的執行不能被其餘事務干擾,即一個事務內部的操做及使用的數據對併發的其餘事務是隔離的,併發執行的各個事務之間不能互相干擾。
  • 持久性(Durability),持久性也稱永久性,指一個事務一旦提交,它對數據庫中數據的改變是永久性的,接下來的其餘操做或故障不該該對其有任何影響。

Spring 事務管理是經過 XML 文件或註解 @Transactional 配置的,其背後是靜態代理或動態代理等技術。在代理模式下,那些從代理傳遞傳過來的「外部」方法調用會被攔截,但「自我調用」是不會觸發事務的。例如,在目標對象中調用自身其餘方法的方法是不會觸發事務的,即便被調用的方法標記爲 @Transactional。性能優化

一般,咱們不多關注 Spring 事務管理相關的屬性,但這些屬性的取值會影響系統的性能。Spring 事務管理最重要的兩個特性是:傳播級別、隔離級別。傳播級別,定義了事務的控制範圍;隔離級別,定義了事務在數據庫讀寫方面的控制範圍。咱們知道,事務的控制範圍越大,系統的併發性就會越差,性能也就隨之下降。事務的隔離級別越高,系統的併發性也會越差,性能也會隨之降低。若是不瞭解這些屬性的取值規則,咱們就不能選擇最合適的取值,不知不覺中就會浪費許多系統資源,接下來咱們一塊兒來看看這些屬性。網絡

屬性 類型 描述
propagation 枚舉型:Propagation 傳播級別,可選,默認值:PROPAGATION_REQUIRED
isolation 枚舉型:Isolation 隔離級別,可選,默認值:ISOLATION_DEFAULT
readOnly 布爾型 讀寫型事務、只讀型事務
timeout INT 型,以秒爲單位 事務超時閾值
rollbackFor 一組 Class 類,必須是 Throwable 的子類 一組異常類,遇到時必須回滾。默認狀況下 Checked Exceptions 不進行回滾,僅 Unchecked Exceptions(即 RuntimeException 的子類)才進行事務回滾。
rollbackForClassname 一組 Class 類的名字,必須是 Throwable 的子類 一組異常類名,遇到時必須回滾
noRollbackFor 一組 Class 類,必須是 Throwable 的子類 一組異常類,遇到時不須要回滾

Spring 事務管理的傳播級別 Propagation 取值有如下幾種: 架構

傳播級別 說明 備註
PROPAGATION_REQUIRED 若是上下文中已經存在事務,那麼就加入到事務中執行;若是上下文中不存在事務,則新建事務執行。 這個級別一般能知足處理大多數的業務場景。
PROPAGATION_SUPPORTS 若是上下文中已經存在事務,則支持加入到事務中執行;若是上下文中不存在事務,則使用非事務的方式執行。 這個一般是用來處理那些並不是原子性的非核心業務邏輯操做,應用場景較少。
PROPAGATION_MANDATORY 該級別的事務要求上下文中必需要存在事務,不然就會拋出異常。這是避免上下文調用代碼遺漏添加事務控制的保證手段。 例如某段代碼不能被單獨調用執行,可是一旦被調用就必需要有事務包含,這種狀況下就可使用這個傳播級別。
PROPAGATION_REQUIRES_NEW 每次都會新建一個事務,而且同時將上下文中的事務掛起,執行當前新建事務完成之後,上下文事務恢復再執行。 問題1:若是某個子事務發生回滾,父事務是否回滾?答案是不會,由於子事務是新建事務,父事務已經被掛起,二者不會受到影響。問題2:若是父事務發生回滾,子事務是否回滾?答案是不會,一樣的理由。可是能夠手動控制,一旦子事務回滾,父事務也回滾。
PROPAGATION_NOT_SUPPORTED 若是上下文中已經存在事務,則掛起事務,執行當前邏輯,結束後恢復上下文的事務。 這個級別能夠幫助你儘量地縮小事務範圍。一個事務範圍越大,它存在的風險也就越多,例如某段代碼是循環 1000 次的非核心業務邏輯操做,此類代碼若是包在事務中,勢必致使事務太大,很容易出現些難以考慮周全的異常狀況,此時這個級別就派上用場了。
PROPAGATION_NEVER 該級別要求上下文中不能存在事務,一旦有事務,就拋出runtime異常,強制中止執行。

 傳播級別 PROPAGATION_REQUIRED 會爲每個被應用到的方法建立一個邏輯事務做用域。每個邏輯事務做用域均可以自主地決定回滾條件,當這樣的邏輯事務做用域被外部邏輯事務做用域所包含時,它們在邏輯上是獨立的,但在實現層面它們會被映射到相同的物理事務上。併發

傳播級別 PROPAGATION_REQUIRES_NEW 爲每個相關的事務做用域使用了一個徹底獨立的事務。在這種狀況下,物理事務也將是不一樣的。所以,外部事務能夠不受內部事務回滾狀態的影響獨立提交或者回滾。

Spring 事務管理的隔離級別 Isolation 取值有如下幾種:

隔離級別 說明
Serializable 最嚴格的級別,事務串行執行,資源消耗最大。
Repeatable Read 保證了一個事務不會修改已經由另外一個事務讀取但未提交(或回滾)的數據,避免了「髒讀取」和「不可重複讀取」的狀況,但會帶來了更多的性能損耗。
Read Committed 大多數主流數據庫的默認事務等級,保證了一個事務不會讀到另外一個並行事務已修改但未提交的數據,避免了「髒讀取」,該級別適用於大多數系統。
Read Uncommitted 保證了讀取過程當中不會讀取到非法數據。

上述說明中涉及的幾個專業術語:

  • 髒讀(Dirty Reads):就是讀到了別的事務回滾前的髒數據。例如,事務 B 執行過程當中修改了數據 X,在未提交前,事務 A 讀取了 X,而事務 B 卻回滾了,這樣事務 A 就造成了髒讀。
  • 不可重複讀(Non-Repeatable Reads):不可重複讀字面含義已經很明確了。例如,事務 A 首先讀取了一條數據,而後執行邏輯的時候,事務 B 將這條數據改變了,而後事務 A 再次讀取的時候,發現數據不匹配了,這就是所謂的不可重複讀。
  • 幻讀(Phantom Reads):咱們小時候數鴨子,第一次數是 10 個,第二次數是 11 個,怎麼回事,產生幻覺了?幻讀也是這樣子,事務 A 先根據條件索引到 10 條數據,而後事務 B 改變了數據庫一條數據,致使也符合事務 A 的搜索條件,這樣事務 A 再次搜索發現有 11 條數據了,這就產生了幻讀。
隔離級別與反作用 髒讀 不可重複讀 幻讀
Serializable 不會 不會 不會
Repeatable Read 不會 不會
Read Committed 不會
Read Uncommitted

從上面這張映射表中,咱們知道最安全的是 Serializable,可是伴隨而來的是高昂的性能開銷。各類傳播級別、隔離級別自己沒有好壞,關鍵是根據業務需求選擇最合適的取值,避免無效的性能損耗。另外,Spring 事務管理還有兩個經常使用屬性,它們的取值也會影響性能:

  • Readonly:只讀型事務要比讀寫型事務的性能更好,設置事務爲只讀以提高性能。
  • Timeout:設置事務的超時時間,通常用於防止大事務的發生,事務要儘量的小。

3.2 二級緩存

緩存做爲提升應用系統性能的一種有效途徑,在事務管理配置不當的狀況下,將很難發揮應有的效用。所以,在作緩存處理或者其餘處理,要考慮事務管理對性能的影響。

 

關注「 IT老兵哥 」,賦能程序人生!堅持原創不易,請小夥伴們不吝點個「  」哦!推薦軟技能文章,請點擊連接:程序員,怎樣打造我的影響力?

 

 

近期熱評系列《 程序員必須懂的架構師入門課 》:

相關文章
相關標籤/搜索