等冪和高並發在電商系統中的使用

來源:互聯網
上載者:User

標籤:

在Java web項目開發中,經常會聽到在做訂單系統中產生訂單的時候,要做等冪性控制和並發控制,特對此部分內容作出總結,在高並發情境下,代碼層面需要實現並發控制;但是等冪性,其實更多的是系統的介面對外的一種承諾,承諾一次請求和多次請求會返回同樣的資料。關於等冪性將分別從高等代數中的等冪性、HTTP中的等冪性和訂單產生系統中的等冪性闡述;並發性控制則提供了分布式鎖等方式來對並發情境進行代碼實現。

一、等冪性 idempotence  [‘a?d?mpo?t?ns]

1.高等代數中關於等冪idempotence概念解釋:

  單目運算, x為某集合內的任意數, 如果滿足f(x)=f(f(x)), 那麼我們稱f運算為具有等冪性(idempotent)。比如在實數集中,絕對值運算就是一個例子: abs(a)=abs(abs(a))。

 

  雙目運算,x為某集合內的任意數, f為運運算元如果滿足f(x,x)=x, f運算的前提是兩個參數都同為x, 那麼我們也稱f運算為具有等冪性。比如在實數集中,求兩個數的最大值的函數: max(x,x) = x, 還有布爾代數中,邏輯運算 "與", "或" 也都是等冪運算, 因為他們符合AND(0,0) = 0, AND(1,1) = 1, OR(0,0) = 0, OR(1,1) = 1。

 

在將等冪性應用到軟體開發中,需要一些更深的理解,我的理解如下:數學處理的是運算和數值, 程式開發中往往處理的是對象和函數. 但是我們不能簡單地理解為數學等冪中的運算就是函數,而數值就是對象。如Person對象有兩個屬性weight和age,但是所有的function只能對其中一個屬性操作。所以從這個層面我們可以理解為: 函數只對該函數所操作的對象某個屬性具有等冪性, 而不是說對整個對象有運算等冪性。

 

Person {     private int weight;     private int age;     //是等冪函數    public void setAge(int v){         this.age = v;     }    //不是等冪函數    public void increaseAge(){         this.age++;    }     //是等冪函數    public void setWeight(int v){         this.weight=v+10;//故意加10斤!!    }}

 

還有一點必須要澄清的是: 等冪性所表達的概念關注的是數學層面的運算和數值, 並沒有提及到數值的安全性問題.如上面的Person的setAge函數, 有兩種case不是等冪性所關心的, 但程式開發卻又必須要關心的:

 

  • 兩個線程同時調用
  • 因為age從業務上講不可能遞減, 如果前一次調用設定是30歲, 後一次調用變成了10歲或是更離譜的 -1 歲

等冪性是系統的介面對外一種承諾(而不是實現), 承諾只要調用介面成功, 外部多次調用對系統的影響是一致的。聲明為等冪的介面會認為外部調用失敗是常態, 並且失敗之後必然會有重試。所以RESTful設計中將等冪性和安全性作為兩個不同的指標來衡量POST,PUT,GET,DELETE操作的。因此,post不是等冪性的,put get delete都是等冪性的,也即在產生訂單的post請求中,我們要做等冪性的控制。如,一個ajax請求是一次post請求的樣本,如果這個post請求被調用多次,它會向表插入多條記錄,很顯然post請求並不是等冪性的,所以等冪性的控制交由我們程式中來控制。

 

2.HTTP協議中的等冪性

  項目中中的SOA和restful API介面的流行,都需要應用程式層HTTP協議的支援,目前的項目結構:Web API + RIA(Rich Internet Applications富互連網應用),Web API專註於提供商務服務,RIA專註於使用者介面和互動設計,從此兩個領域的分工更加明晰。正如簡單的Java語言並不意味著高品質的Java程式,簡單的HTTP協議也不意味著高品質的Web API。要想設計出高品質的Web API,還需要深入理解分布式系統及HTTP協議的特性。在HTTP1.1規範中定義等冪性。

 

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects 
  of N > 0 identical requests is the same as for a single request.

 

從定義上看,HTTP方法的等冪性是指一次和多次請求某一個資源應該具有同樣的作用。等冪性是分布式系統設計中十分重要的概念,而HTTP的分布式本質也決定了它在HTTP中具有重要地位。比如有這樣一個商務邏輯,假設有一個從賬戶取錢的遠程API(可以是HTTP的,也可以不是),我們暫時定義介面:

 

bool withdraw(account_id, amount)

 

withdraw的語義是從account_id對應的賬戶中扣除amount數額的錢;如果扣除成功則返回true,賬戶餘額減少amount;如果扣除失敗則返回false,賬戶餘額不變。值得注意的是:和本地環境相比,我們不能輕易假設分布式環境的可靠性。一種典型的情況是withdraw請求已經被伺服器端正確處理,但伺服器端的返回結果由於網路等原因被丟掉了,導致用戶端無法得知處理結果。如果是在網頁上,一些不恰當的設計可能會使使用者認為上一次操作失敗了,然後重新整理頁面,這就導致了withdraw被調用兩次,賬戶也被多扣了一次錢。如所示:

 

這個問題的解決方案一是採用分散式交易,通過引入支援分散式交易的中介軟體來保證withdraw功能的事務性。分散式交易的優點是對於調用者很簡單,複雜性都交給了中介軟體來管理。缺點則是一方面架構太重量級,容易被綁在特定的中介軟體上,不利於異構系統的整合;另一方面分散式交易雖然能保證事務的ACID性質,而但卻無法提供效能和可用性的保證。

  另一種更輕量級的解決方案是等冪設計。我們可以通過一些技巧把withdraw變成等冪的,比如:

 

int create_ticket() bool idempotent_withdraw(ticket_id, account_id, amount)

 

create_ticket的語義是擷取一個伺服器端產生的唯一的處理號token,它將用於標識後續的操作。idempotent_withdraw和withdraw的區別在於關聯了一個token,一個token表示的操作至多隻會被處理一次,每次調用都將返回第一次調用時的處理結果。這樣,idempotent_withdraw就符合等冪性了,用戶端就可以放心地多次調用。也就是說,多次點擊提交的時候,附帶提交的還有服務端產生的token,由於多次提交帶的是同一個token,所以服務端對於同一個token的post訂單,至多隻會處理一次,所以間接的實現了等冪性的控制。

基於等冪性的解決方案中一個完整的取錢流程被分解成了兩個步驟:1.調用create_ticket()擷取token;2.調用idempotent_withdraw(token, account_id, amount)。雖然create_ticket不是等冪的,但在這種設計下,它對系統狀態的影響可以忽略,加上idempotent_withdraw是等冪的,所以任何一步由於網路等原因失敗或逾時,用戶端都可以重試,直到獲得結果。2所示:

 

和分散式交易相比,等冪設計的優勢在於它的輕量級,容易適應異構環境,以及效能和可用性方面。在某些效能要求比較高的應用中,等冪設計往往是唯一的選擇。

  1. HTTP GET方法用於擷取資源,不應有副作用,所以是等冪的。比如:GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次還是N次都沒有副作用。請注意,這裡強調的是一次和N次具有相同的作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次得到不同的結果,但它本身並沒有產生任何副作用,因而是滿足等冪性的。
  2. HTTP DELETE方法用於刪除資源,有副作用,但它應該滿足等冪性。比如:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的副作用是相同的,即刪掉id為4231的文章;因此,調用者可以多次調用或重新整理頁面而不必擔心引起錯誤。
  3. 比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認為“POST表示建立資源,PUT表示更新資源”;而實際上,二者均可用於建立資源,更為本質的差別是在等冪性方面。在HTTP規範中對POST和PUT是這樣定義的:

 

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified 
by the Request-URI in the Request-Line ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain
an entity which describes the status of the request and refers to the new resource, and a Location header.The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource,
the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an
existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

 

POST所對應的URI並非建立的資源本身,而是資源的接收者。比如:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下建立一篇文章,HTTP響應中應包含文章的建立狀態以及文章的URI。兩次相同的POST請求會在伺服器端建立兩份資源,它們具有不同的URI;所以,POST方法不具備等冪性。而PUT所對應的URI是要建立或更新的資源本身。比如:PUT http://www.forum/articles/4231的語義是建立或更新ID為4231的文章。對同一URI進行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有等冪性。論壇網站防止重複發帖和訂單產生都用到token方式的等冪性控制。

3.總結

  在電商系統中,常見問題:如何防範post請求的重複提交?HTTP POST 操作既不是安全的,也不是等冪的。當我們因為反覆重新整理瀏覽器導致多次提交表單,多次發出同樣的POST請求,導致遠端伺服器重複建立出了資源。所以,對於電商應用來說,第一對應的後端 WebService 一定要做到等冪性,第二伺服器端收到 POST 請求,在操作成功後必須跳轉到另外一個頁面,這樣即使使用者重新整理頁面,也不會重複提交表單

二、高並發

 

1.分布式鎖的定義

  分布式鎖是控制分布式系統之間同步訪問共用資源的一種方式。在分布式系統中,常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共用了一個或一組資源,那麼訪問這些資源的時候,往往需要互斥來防止彼此幹擾來保證一致性,在這種情況下,便需要使用到分布式鎖。分布式鎖是一個在很多環境中非常有用的原語,它是不同的系統或是同一個系統的不同主機之間互斥操作共用資源的有效方法。如在電商系統中,需要保證整個分布式系統內,對一個重要事物(訂單,賬戶等)的有效操作線程 ,同一時間內有且只有一個。比如交易中心有N台伺服器,訂單中心有M台伺服器,如何保證一個訂單的同一筆支付處理,一個賬戶的同一筆儲值操作是原子性的。

  常見的實現分布式鎖的服務有:memcache zookeeper redis chubby hazelcast。

2.分布式鎖實現

  分布式鎖在分布式應用當中是要經常用到的,主要是解決分布式資源存取違規的問題。傳統的鎖ReentrantLock在去實現的時候是有問題的,ReentrantLock的lock和unlock要求必須是在同一線程進行,而分布式應用中,lock和unlock是兩次不相關的請求,因此肯定不是同一線程,因此導致無法使用ReentrantLock。

 

附:

1、什麼是restful風格的API介面?

http://www.ruanyifeng.com/blog/2014/05/restful_api.html

http://www.cnblogs.com/zhengyun_ustc/archive/2012/11/17/topic2.html

http://www.cnblogs.com/j2eetop/p/4612437.html

http://www.cnblogs.com/weidagang2046/p/exception-handling-principles.html

http://www.cnblogs.com/orange1438/p/4637776.html

 

等冪和高並發在電商系統中的使用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.