成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入理解JTS平衡安全性和性能

開發 后端
本文深入介紹了JTS平衡安全性和性能,希望對你有幫助,一起來看吧!

JTS 只是一個組件事務監視器(有時也稱為 對象事務監視器(object transaction monitor)),或稱為 CTM。大家可以看看這篇文章,Java理論和實踐: 理解JTS

事務主要是一種異常處理機制。事務在程序中的用途與合法合同在日常業務中的用途相似:如果出了什么問題它們可以幫助恢復。但由于大多數時間內都沒實際 發生什么錯誤,我們就希望能夠盡量減少它們的開銷以及對其余時間的占用。我們在應用程序中如何使用事務會對應用程序的性能和可伸縮性產生很大的影響。

事務劃分

J2EE 容器提供了兩種機制用來定義事務的起點和終點:bean 管理的事務和容器管理的事務。在 bean 管理的事務中,用 UserTransaction.begin() 和 UserTransaction.commit() 在 bean 方法中顯式開始和結束一個事務。另一方面,容器管理的事務提供了更多的靈活性。通過在裝配描述符中為每個 EJB 方法定義事務性屬性,您可以指定每個方法的事務性需求并讓容器確定何時開始和結束一個事務。無論在哪種情況下,構建事務的基本指導方針都是一樣的。

進來,出去

事務劃分的第一條規則是“盡量短小”。事務提供并發控制;這通常意味著資源管理器將代表您獲得您在事務期間訪問的數據項的鎖,并且它必須一直持有這些鎖,直到事務結束。(請回憶一下本系列第 1 部分所討論的 ACID特性,其中“ACID”的“I”代表“隔離”(Isolation)。也就是說,一個事務的結果影響不到與該事務并發執行的其它事務。)當您擁有鎖時,任何需要訪問您鎖定的數據項的其它事務將不得不一直等待,直到您釋放鎖。如果您的事務很長,那些其它的所有事務都將被鎖定,您的應用程序吞吐量將大幅度下降。

規則 1:使事務盡可能短小。

通過使事務盡量短小,您可以把阻礙其它事務的時間縮到最短,從而提高應用程序的可伸縮性。保持事務盡可能短小的最好方法當然是不在事務中間做任何不必要耗費時間的事,特別是不要在事務中間等待用戶輸入。

開始一個事務,從數據庫檢索一些數據,顯示數據,然后在仍處于事務中時請用戶做出一個選擇可能比較誘人。千萬別這么做!即使用戶注意力集中,也要花費數秒來響應 ― 而在數據庫中擁有鎖數秒的時間已經是很長的了。如果用戶決定離開計算機,或許是去吃午餐或者甚至回家一天,會發生什么情況?應用程序將只好無奈停機。在事務期間執行 I/O 是導致災難的秘訣。

規則 2:在事務期間不要等待用戶輸入。

將相關的操作歸在一起

由于每個事務都有不小的開銷,您可能認為最好是在單個事務中執行盡可能多的操作以使每個操作的開銷達到最小。但規則 1 告訴我們長事務對可伸縮性不利。那么如何實現最小化每個操作的開銷和可伸縮性之間的平衡呢?

我們把規則 1 設置為邏輯上的極端 ― 每個事務一個操作 ― 這樣不僅會導致額外開銷,還會危及應用程序狀態的一致性。假定事務性資源管理器維護應用程序狀態的一致性(請回憶一下第 1 部分,其中“ACID”的“C”代表“一致性”(Consistency)),但它們依賴應用程序來定義一致性的意思。實際上,我們在描述事務時使用的一致性的定義有點圓滑:應用程序說一致性是什么意思它就是什么意思。應用程序把幾組應用程序狀態的變化組織到幾個事務中,結果應用程序的狀態就成了 定義上的(by definition)一致。然后資源管理器確保如果它必須從故障恢復的話,就把應用程序狀態恢復到最近的一致狀態。

在第 1 部分中,我們給出了一個在銀行應用程序中將資金從一個帳戶轉移到另一個帳戶的示例。清單 1 展示了這個示例可能的 SQL 實現,它包含 5 個 SQL 操作(一個選擇,兩個更新和兩個插入操作):

清單 1. 資金轉移的樣本 SQL 代碼

  1.  
  2. SELECT accountBalance INTO aBalance   
  3. FROM Accounts WHERE accountId=aId;  
  4. IF (aBalance >= transferAmount) THEN   
  5. UPDATE Accounts   
  6. SET accountBalance = accountBalance - transferAmount  
  7. WHERE accountId = aId;  
  8. UPDATE Accounts   
  9. SET accountBalance = accountBalance + transferAmount  
  10. WHERE accountId = bId;  
  11. INSERT INTO AccountJournal (accountId, amount)  
  12. VALUES (aId, -transferAmount);  
  13. INSERT INTO AccountJournal (accountId, amount)  
  14. VALUES (bId, transferAmount);  
  15. ELSE 
  16. FAIL "Insufficient funds in account";  
  17. END IF 

如果我們把這個操作作為五個單獨的事務來執行會發生什么情況?這樣不僅會使執行速度變慢(由于事務開銷),還會失去一致性。例如,如果一個人從帳戶 A 取了錢,作為執行第一次 SELECT(檢查余額)和隨后的記入借方 UPDATE 之間的一個單獨事務的一部分,會發生什么情況?這樣會違反我們認為這段代碼會強制遵守的業務規則 ― 帳戶余額應該是非負的。如果在第一次 UPDATE 和第二次 UPDATE 之間系統失敗會發生什么情況?現在,當系統恢復時,錢已經離開了帳戶 A 但還沒有記入帳戶 B 的貸方,并且也無記錄說明原因。這樣,哪個帳戶的所有者都不會開心。

清單 1 中的五個 SQL 操作是單個相關操作 ― 將資金從一個帳戶轉移到另一個帳戶 ― 的一部分。因此,我們希望要么全部執行它們,要么一個也不執行,建議在單個事務中全部執行它們。

規則 3:將相關操作歸到單個事務中。

理想化的平衡

規則 1 說事務應盡可能短小。清單 1 中的示例表明有時候我們必須把一些操作歸到一個事務中來維護一致性。當然,它要依賴應用程序來確定“相關操作”是由什么組成的。我們可以把規則 1 和 3 結合在一起,提供一個描述事務范圍的一般指導,我們規定它為規則 4:

規則 4:把相關操作歸到單個事務中,但把不相關的操作放到單獨的事務中。

容器管理的事務

在使用容器管理的事務時,不是顯式聲明事務的起點和終點,而是為每個 EJB 方法定義事務性需求。bean 的 assembly-descriptor 的 container-transaction 部分的 trans-attribute 元素中定義了事務模式。(清單 2 中顯示了一個 assembly-descriptor 示例。)方法的事務模式以及狀態 ― 調用方法是否早已在事務中被征用 ― 決定了當 EJB 方法被調用時容器應該進行下面幾個操作中的哪一個:

征用現有事務中的方法。

創建一個新事務,并征用該事務中的方法。

不征用任何事務中的方法。

拋出一個異常。

清單 2. 樣本 EJB 裝配描述符

  1. <assembly-descriptor>  
  2. ...  
  3. <container-transaction>  
  4. <method>  
  5. <ejb-name>MyBean</ejb-name>  
  6. <method-name>*</method-name>  
  7. </method>  
  8. <trans-attribute>Required</trans-attribute>  
  9. </container-transaction>  
  10. <container-transaction>  
  11. <method>  
  12. <ejb-name>MyBean</ejb-name>  
  13. <method-name>logError</method-name>  
  14. </method>  
  15. <trans-attribute>RequiresNew</trans-attribute>  
  16. </container-transaction>  
  17. ...  
  18. </assembly-descriptor> 

那么我們應該為自己的 bean 方法選擇哪種模式呢?對于會話 bean 和消息驅動 bean,您通常想使用 Required 來確保每個調用都被作為事務的一部分執行,但仍將允許方法作為一個更大的事務的組件。請小心使用 RequiresNew ;只有在確定自己的方法的行為應該與調用您的方法的行為分開提交時,才應該使用這種模式。 RequiresNew 一般情況下只和與系統中其它對象關系很少或沒什么關系的對象(比如日志對象)一起使用。(把 RequiresNew 與日志對象一起使用比較有意義,因為您可能希望在不管外圍事務是否提交的情況下提交日志消息。)

RequiresNew 使用不當會導致與上面的描述相似的情況,其中,清單 1 中的代碼在五個分開的事務而不是一個事務中執行,這樣會使應用程序處于不一致狀態。

對于 CMP(容器管理的持久性,container-managed persistence)實體 bean,通常是希望使用 Required 。 Mandatory 也是一個合理的選項,特別是在最初開發時;這將會警告您實體 bean 方法在事務外被調用這種情況,這時可能會指出一個部署錯誤。您幾乎從不希望把 RequiresNew 和 CMP 實體 bean 一起使用。 NotSupported 和 Never 旨在用于非事務性資源,比如 Java 事務 API(Java Transaction API,JTA)事務中無法征用的外部非事務性系統或事務性系統的適配器。

如果 EJB 應用程序設計得當,應用上面的事務模式指導往往會自然地產生規則 4 建議的事務劃分。原因是 J2EE 體系架構鼓勵把應用程序分解為最小的方便處理的塊,并且每個塊都作為一個單獨的請求被處理( 不管是以 HTTP 請求的形式還是作為在 JMS 隊列中排隊的消息的結果)。

重溫隔離

在第 1 部分中,我們定義了 隔離(isolation)的意思是:一個事務的影響對與該事務并發執行的其它事務是不可見的;從事務的角度來看,好象事務是連續執行而非并行執行。盡管事務性資源管理器經常可以同時處理許多事務并提供隔離的假象,但有時隔離限制實際上要求把新事務延遲到現有事務完成后才開始。由于完成一個事務至少包括一個同步磁盤 I/O(寫到事務日志),這就會把每秒的事務數限制到接近每秒的寫磁盤次數,這對可伸縮性不利。

實際上,通常是充分放松隔離需求以允許更多的事務并發執行并使系統響應能夠得到改善,使可伸縮性變得更強。幾乎所有的數據庫都支持標準隔離級別:讀未提交的(Read Uncommitted)、讀已提交的(Read Committed)、可重復的讀(Repeatable Read) 和可串行化的(Serializable)。

不幸的是,為容器管理的事務管理隔離目前是在 J2EE 規范的范圍之外。但是,許多 J2EE 容器,比如 IBM WebSphere 和 BEA WebLogic,將提供特定于容器的擴展,這些擴展允許您以每方法(per-method)為基礎設置事務隔離級別,設置方法與在裝配描述符中設置事務模式的方法相同。對于 bean 管理的事務,您可以通過 JDBC 或者其它資源管理器連接設置隔離級別。

為闡明隔離級別之間的差異,我們首先把幾個并發危險分類 ― 這幾種危險是當沒有適當地隔離時一個事務可能會干涉另一個事務的情況。下列的所有這些危險都與這種情況( 第二個事務已經啟動后第一個事務變得對第二個事務 可見)的結果有關:

臟讀(Dirty Read):當一個事務的中間(未提交的)結果對另一個事務可見時就會發生這種情況。

不可重復的讀(Unrepeatable Read):當一個事務讀取一個數據項,然后重新讀取這個數據項并看到不同的值時就是發生了這種情況。

虛讀(Phantom Read):當一個事務執行返回多個行的查詢,稍后再次執行同一個查詢并看到第一次執行該查詢沒出現的額外行時就是發生了這種情況。

四個標準隔離級別與這三個隔離危險相關,如表 2 所示。最低的隔離級別“讀未提交的”并不能保護事務不被其它事務更改,但它的速度最快,因為它不需要爭奪讀鎖。最高的隔離級別“可串行化的”與上面給出的隔離的定義相當;每個事務好象都與其它事務的影響完全隔離。

表 2. 事務隔離級別

事務隔離級別

對于大多數數據庫,缺省的隔離級別為“讀已提交的”,這是個很好的缺省選擇,因為它阻止事務在事務中的任何給定的點看到應用程序數據的不一致視圖。“讀已提交的”是一個很不錯的隔離級別,用于大多數典型的短事務,比如獲取報表數據或獲取要顯示給用戶的數據的時候(多半是作為 Web 請求的結果),也用于將新數據插入到數據庫的情況。

當您需要所有事務間有較高級別的一致性時,使用較高的隔離級別“可重復的讀”和“可串行化的”比較合適,比如在清單 1 示例中,您希望從檢查余額以確保有足夠的資金到您實際取錢期間賬戶余額一直保持不變;這就要求至少要用“可重復的讀”隔離級別。在數據一致性絕對重要的情況下,比如審核記帳數據庫以確保一個帳戶的所有借方金額和貸方金額的總數等于它目前的余額時,可能還需要防止創建新行。這種情況下就需要使用“可串行化的”隔離級別。

最低的隔離級別“讀未提交的”很少使用。它適用于您只需要獲得近似值,否則查詢將導致您不希望的性能開銷這種情況。當您想要估計一個變化很快的數量,如定單數或者今天所下定單的總金額(以美元為單位)時一般使用““讀未提交的”。

因為隔離和可伸縮性之間實際是一種此消彼長的關系,所以您在為事務選擇隔離級別時應該小心行事。選擇太低的級別對數據比較危險。選擇太高的級別可能對性能不利,盡管負載比較輕時可能不會這樣。一般來說,數據一致性問題比性能問題更嚴重。如果拿不準,應該以小心為主,選擇一個較高的隔離級別。這就引出了規則 5:

規則 5:使用保證數據安全 style="COLOR: #000000" href="http://safe.it168.com/" target=_blank>安全的最低隔離級別,但如果拿不準,請使用“可串行化的”。

即使您打算剛開始時以小心為主并希望結果性能可以接受 ―(被稱為“拒絕和祈禱(denial and prayer)”的性能管理技術 ― 很可能是最常用的性能策略,盡管大多數開發者都不承認這一點),在開發組件時考慮隔離需求也是有利的。您應該努力編寫能夠容忍級別較低但實用的隔離級別的事務,這樣,當稍后性能成為問題時,自己就不會陷入困境。因為您需要知道方法正在做什么以及這個方法中隱藏了什么一致性假設來正確設置隔離級別,那么在開發期間仔細說明并發需求和假設,以便在裝配應用程序時幫助作出正確的決定也不失為一個好主意。

結束語

本文中提供的許多指導可能看起來有點互相矛盾,因為象事務劃分和隔離這種問題本來就是此消彼長的。我們正在努力平衡安全性(如果我們不關心安全性,那就壓根不必用事務了)和我們用來提供安全限度的工具的性能開銷。正確的平衡要依賴許多因素,包括與系統故障或當機時間相關的代價或損害以及組織的風險承受能力。

【編輯推薦】

  1. java/.net語言及IDE簡易對比
  2. java中的類和方法的修飾符
  3. 關于Java對象序列化您不知道的5件事
  4. Java為什么如此深受廣大開發者的青睞?
  5. Javascript中的函數聲明和函數表達式
責任編輯:于鐵 來源: 互聯網
相關推薦

2023-06-01 15:17:17

2019-04-08 16:50:33

前端性能監控

2023-06-29 00:17:58

DevSecOps軟件開發

2009-06-19 14:10:42

Java多態性

2024-11-14 16:02:43

2009-11-09 17:40:33

WCF配置可靠性

2009-10-12 10:52:47

RHEL5安全性

2022-01-18 10:48:12

HTTPS加密安全漏洞

2015-05-11 10:42:17

混合云性能混合云安全SLA

2024-06-06 09:58:13

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數據結構hash函數

2020-07-21 08:26:08

SpringSecurity過濾器

2012-08-31 10:00:12

Hadoop云計算群集網絡

2012-11-08 14:47:52

Hadoop集群

2013-07-31 10:04:42

hadoopHadoop集群集群和網絡

2025-01-13 13:00:00

Go網絡框架nbio

2009-06-25 13:21:00

JTS

2012-12-21 15:24:53

Android 上的安全性

2016-07-05 10:50:44

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99这里只有精品视频 | 一区二区三区免费 | 久久一热 | 国产免费av网| 午夜小电影 | 国产在线中文字幕 | 国产精品激情 | 亚洲在线视频 | 欧美性乱| 久久久久久久久久久久久9999 | 日韩在线中文 | 国产精品久久久 | 欧美精品三区 | 久久国产精品视频 | 91精品国产一区二区三区香蕉 | 久久久久久久久久久久久久久久久久久久 | 欧美一区二区三区久久精品 | 久草在线| 欧美一级黄带 | 国产精品无码专区在线观看 | 亚洲 精品 综合 精品 自拍 | 亚洲精品一区中文字幕 | 狠狠干在线| 日韩精品一区二区三区在线播放 | 欧美中文字幕一区二区 | 日韩精品一区二区三区免费视频 | 亚洲精品一区二区三区蜜桃久 | 日韩精品视频在线观看一区二区三区 | 国产精品久久久久久久久久 | 国产美女福利在线观看 | 久久久久久91| 国产亚洲高清视频 | 中文字幕 国产 | 国产精品99久| 成人区精品一区二区婷婷 | 国产精品夜夜夜一区二区三区尤 | 亚洲精品第一国产综合野 | 国产午夜影院 | 北条麻妃99精品青青久久 | 最新av在线网址 | 国产精品中文在线 |