大多數(shù)基于web的業(yè)務(wù)應(yīng)用遵循相同的通用請求流程:來自瀏覽器的請求先到達web服務(wù)器恩急,然后是應(yīng)用服務(wù)器终畅,最后是數(shù)據(jù)庫服務(wù)器盆犁。雖然這種模式對小用戶量非常有效酥艳,但是隨著用戶負載的增加,瓶頸開始出現(xiàn)拭卿,首先是在web服務(wù)器層骡湖,然后是在應(yīng)用服務(wù)器層,最后是在數(shù)據(jù)庫服務(wù)器層峻厚。對于解決用戶負載增加產(chǎn)生的瓶頸响蕴,通常的反應(yīng)是橫向擴展web服務(wù)器。這是相對容易和便宜的方案惠桃,它有時可以解決瓶頸問題浦夷。然而,在大多數(shù)高用戶負載的情況下辜王,擴展web服務(wù)器層只會將瓶頸向下移動到應(yīng)用服務(wù)器劈狐。擴展應(yīng)用程序服務(wù)器可能比web服務(wù)器更復(fù)雜、更昂貴呐馆,而且通常只會將瓶頸轉(zhuǎn)移到數(shù)據(jù)庫服務(wù)器上肥缔,而數(shù)據(jù)庫服務(wù)器的擴展則更加困難和昂貴。即使你可以擴展數(shù)據(jù)庫摹恰,你最終得到的是一個三角形的拓撲結(jié)構(gòu)辫继,三角形最寬的部分是web服務(wù)器(最容易擴展),最小的部分是數(shù)據(jù)庫(最難擴展)俗慈,如圖15-1所示姑宽。
在任何具有大量并發(fā)用戶負載的大容量應(yīng)用中,數(shù)據(jù)庫通常是你可以并發(fā)處理多少事務(wù)的最終限制因素闺阱。雖然各種緩存技術(shù)和數(shù)據(jù)庫擴展產(chǎn)品有助于解決這些問題炮车,但事實仍然是,為極端負載擴展普通應(yīng)用程序是一個非常困難的命題酣溃。
基于空間的架構(gòu)風(fēng)格是專門為解決涉及高可擴展性瘦穆、彈性和高并發(fā)性問題而設(shè)計的。對于具有可變和不可預(yù)測的并發(fā)用戶量的應(yīng)用赊豌,它也是一種有用的架構(gòu)風(fēng)格扛或。從架構(gòu)上解決極端和可變的可擴展性問題通常比嘗試擴展數(shù)據(jù)庫或?qū)⒕彺婕夹g(shù)改造為不可擴展的架構(gòu)要好。
一般拓撲結(jié)構(gòu)
基于空間的體系結(jié)構(gòu)得名于元組空間的概念碘饼,這種技術(shù)使用多個并行處理器通過共享內(nèi)存進行通信熙兔。通過消除系統(tǒng)中作為同步約束的中央數(shù)據(jù)庫悲伶,而利用自我復(fù)制的內(nèi)存中的數(shù)據(jù)網(wǎng)格,實現(xiàn)了高可擴展性住涉、高彈性和高性能麸锉。應(yīng)用數(shù)據(jù)保存在內(nèi)存中,并在所有活動處理單元之間進行復(fù)制舆声。當(dāng)處理單元更新數(shù)據(jù)時花沉,它將數(shù)據(jù)異步發(fā)送到數(shù)據(jù)庫,通常是通過具有持久化隊列的消息傳遞媳握。處理單元隨著用戶負載的增加和減少而動態(tài)啟動和關(guān)閉碱屁,從而解決了可變的可擴展性問題。因為在應(yīng)用的標準事務(wù)處理中不涉及中央數(shù)據(jù)庫毙芜,所以數(shù)據(jù)庫瓶頸被消除忽媒,從而在應(yīng)用中提供近乎無限的可擴展性。
幾個架構(gòu)組件組成了一個基于空間的架構(gòu):包含應(yīng)用程序代碼的處理單元腋粥、用于管理和協(xié)調(diào)處理單元的虛擬化中間件、異步地將更新數(shù)據(jù)發(fā)送到數(shù)據(jù)庫的數(shù)據(jù)泵架曹、從數(shù)據(jù)泵執(zhí)行更新的數(shù)據(jù)寫入器以及在啟動時讀取數(shù)據(jù)庫數(shù)據(jù)并將其傳遞給處理單元的數(shù)據(jù)讀取器隘冲。圖15-2說明了這些主要的架構(gòu)組件。
處理單元
處理單元(如圖15-3所示)包含應(yīng)用程序邏輯(或應(yīng)用程序邏輯的一部分)绑雄。這通常包括基于web的組件以及后端業(yè)務(wù)邏輯展辞。處理單元的內(nèi)容因應(yīng)用的類型而異。較小的web應(yīng)用可能部署到單個處理單元中万牺,而較大的應(yīng)用可能會根據(jù)應(yīng)用的功能劃分為多個處理單元罗珍。處理單元還可以包含小型的、單一用途的服務(wù)(與微服務(wù)一樣)脚粟。除了應(yīng)用程序邏輯之外覆旱,處理單元還包含一個內(nèi)存中的數(shù)據(jù)網(wǎng)格和復(fù)制引擎,通常通過Hazelcast核无、Apache Ignite和Oracle Coherence等產(chǎn)品實現(xiàn)扣唱。
虛擬化中間件
虛擬化中間件處理架構(gòu)中控制數(shù)據(jù)同步和請求處理各個方面的基礎(chǔ)設(shè)施問題。組成虛擬化中間件的組件包括消息傳遞網(wǎng)格团南、數(shù)據(jù)網(wǎng)格噪沙、處理網(wǎng)格和部署管理器。這些組件(將在下一節(jié)中詳細描述)可以定制編寫或通過購買第三方產(chǎn)品實現(xiàn)吐根。
消息傳遞網(wǎng)格
消息傳遞網(wǎng)格正歼,如圖15-4所示,管理輸入請求和會話狀態(tài)拷橘。當(dāng)一個請求進入虛擬化中間件時局义,消息傳遞網(wǎng)格組件確定哪些活動處理組件可用于接收請求齐疙,并將請求轉(zhuǎn)發(fā)給這些處理單元之一。消息傳遞網(wǎng)格的復(fù)雜性可以從簡單的循環(huán)算法到更復(fù)雜的next-available算法旭咽,該算法跟蹤哪個請求由哪個處理單元處理贞奋。該組件通常使用具有負載均衡功能的傳統(tǒng)web服務(wù)器(如HA-Proxy和Nginx)實現(xiàn)。
數(shù)據(jù)網(wǎng)格
數(shù)據(jù)網(wǎng)格組件可能是這種架構(gòu)風(fēng)格中最重要和最關(guān)鍵的組件穷绵。在大多數(shù)現(xiàn)代實現(xiàn)中轿塔,數(shù)據(jù)網(wǎng)格是作為復(fù)制緩存在處理單元中單獨實現(xiàn)的。但是仲墨,對于那些需要外部控制器的復(fù)制緩存實現(xiàn)勾缭,或者在使用分布式緩存時,此功能將駐留在處理單元目养,以及虛擬化中間件中的數(shù)據(jù)網(wǎng)格組件中俩由。由于消息傳遞網(wǎng)格可以將請求轉(zhuǎn)發(fā)給任何可用的處理單元,因此每個處理單元在其內(nèi)存數(shù)據(jù)網(wǎng)格中包含完全相同的數(shù)據(jù)是至關(guān)重要的癌蚁。雖然圖15-5顯示了處理單元之間的同步數(shù)據(jù)復(fù)制幻梯,但實際上這是以異步和非常快速的方式完成的努释,通常在不到100毫秒的時間內(nèi)完成數(shù)據(jù)同步碘梢。
數(shù)據(jù)在包含相同命名數(shù)據(jù)網(wǎng)格的處理單元之間同步。為了說明這一點伐蒂,請考慮使用Hazelcast的以下Java代碼煞躬,該代碼為包含客戶概要信息的處理單元創(chuàng)建一個內(nèi)部復(fù)制的數(shù)據(jù)網(wǎng)格:
HazelcastInstance hz = Hazelcast.newHazelcastInstance();?
Map<String, CustomerProfile> profileCache =????
????hz.getReplicatedMap("CustomerProfile");
所有需要訪問客戶概要信息的處理單元都將包含此段代碼。從任何處理單元對名為CustomerProfile的緩存所做的更改將使該更改復(fù)制到包含相同命名緩存的所有其他處理單元逸邦。處理單元可以包含完成其工作所需的任意數(shù)量的復(fù)制緩存恩沛。或者缕减,一個處理單元可以遠程調(diào)用另一個處理單元以請求數(shù)據(jù)(編排)或利用處理網(wǎng)格(在下一節(jié)中描述)來編制請求雷客。
處理單元中的數(shù)據(jù)復(fù)制還允許服務(wù)實例上下移動,而不必從數(shù)據(jù)庫中讀取數(shù)據(jù)烛卧,前提是至少有一個實例包含命名的復(fù)制緩存佛纫。當(dāng)一個處理單元實例啟動時,它連接到緩存提供程序(如Hazelcast)并請求獲取指定的緩存总放。當(dāng)連接到其他處理單元后呈宇,緩存將從其中一個實例中加載。
每個處理單元通過使用成員列表了解所有其他處理單元實例局雄。成員列表包含使用同一命名緩存的所有其他處理單元的IP地址和端口甥啄。例如,假設(shè)有一個處理實例包含客戶概要文件的代碼和復(fù)制的緩存數(shù)據(jù)炬搭。在這種情況下蜈漓,只有一個實例穆桂,因此該實例的成員列表只包含自身,如使用Hazelcast生成的以下日志語句所示:
Instance 1:
Members {size:1, ver:1} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this
]
當(dāng)另一個處理單元使用相同的命名緩存啟動時融虽,兩個服務(wù)的成員列表都會更新享完,以反映每個處理單元的IP地址和端口:
Instance 1:
Members {size:2, ver:2} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this?
??? Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
]?
Instance 2:
Members {size:2, ver:2} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
??? Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this
]
當(dāng)?shù)谌齻€處理單元啟動時,實例1和實例2的成員列表都會更新以反映新的第三個實例:
Instance 1:
Members {size:3, ver:3} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this?
??? Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
??? Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]?
Instance 2:
Members {size:3, ver:3} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
??? Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this??
??? Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]?
Instance 3:
Members {size:3, ver:3} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
??? Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
??? Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this
]
請注意有额,這三個實例都知道彼此(包括它們自己)般又。假設(shè)實例1接收到更新客戶概要信息的請求。當(dāng)實例1使用cache.put()或類似的緩存更新方法巍佑,數(shù)據(jù)網(wǎng)格(如Hazelcast)將使用相同的更新異步更新其他復(fù)制的緩存茴迁,確保所有三個客戶概要文件緩存始終保持彼此同步。
當(dāng)處理單元關(guān)閉時萤衰,其他處理單元自動更新以反映丟失的成員堕义。例如,如果實例2關(guān)閉脆栋,實例1和實例3的成員列表將更新如下:
Instance 1:
Members {size:2, ver:4} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this?
??? Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]?
Instance 3:
Members {size:2, ver:4} [????
??? Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
??? Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this
]
處理網(wǎng)格
圖15-6所示的處理網(wǎng)格是虛擬化中間件中的一個可選組件倦卖,當(dāng)單個業(yè)務(wù)請求中涉及多個處理單元時,它管理編排好的請求處理筹吐。如果請求需要處理單元類型(例如糖耸,訂單處理單元和付款處理單元)之間的協(xié)調(diào),則處理網(wǎng)格將在這兩個處理單元之間協(xié)調(diào)和編排請求丘薛。
部署管理器
部署管理器組件根據(jù)負載條件管理處理單元實例的動態(tài)啟動和關(guān)閉。此組件持續(xù)監(jiān)控響應(yīng)時間和用戶負載邦危,在負載增加時啟動新的處理單元洋侨,在負載降低時關(guān)閉處理單元。這是一個在應(yīng)用中實現(xiàn)可變可伸縮性(彈性)需求的關(guān)鍵組件倦蚪。
數(shù)據(jù)泵
數(shù)據(jù)泵是一種將數(shù)據(jù)發(fā)送到另一個處理器的方法希坚,然后另一個處理器更新數(shù)據(jù)庫中的數(shù)據(jù)。數(shù)據(jù)泵是基于空間的架構(gòu)中的一個必要組件陵且,因為處理單元不直接讀寫數(shù)據(jù)庫裁僧。數(shù)據(jù)泵在基于空間的架構(gòu)中始終是異步的,提供與內(nèi)存緩存和數(shù)據(jù)庫的最終一致性慕购。當(dāng)處理單元實例接收到請求并更新其緩存時聊疲,該處理單元成為更新的所有者,因此負責(zé)通過數(shù)據(jù)泵發(fā)送更新沪悲,以便最終更新數(shù)據(jù)庫获洲。
數(shù)據(jù)泵通常使用消息傳遞來實現(xiàn),如圖15-7所示殿如。在使用基于空間的架構(gòu)時贡珊,消息傳遞是數(shù)據(jù)泵的一個不錯的選擇最爬。消息傳遞不僅支持異步通信,還支持通過先進先出(FIFO)隊列保證傳遞和保持消息順序门岔。此外爱致,消息傳遞在處理單元和數(shù)據(jù)寫入器之間提供了解耦,以便在數(shù)據(jù)寫入器不可用的情況下寒随,仍可以在處理單元內(nèi)進行不間斷的處理糠悯。
在大多數(shù)情況下會有多個數(shù)據(jù)泵,每一個通常專用于特定的領(lǐng)域或子領(lǐng)域(如客戶或庫存)牢裳。數(shù)據(jù)泵可以專用于每種類型的緩存(例如CustomerProfile逢防、CustomerWishlist等),也可以專用于包含更大的和通用緩存的處理單元領(lǐng)域(如Customer)蒲讯。
數(shù)據(jù)泵通常具有關(guān)聯(lián)的契約忘朝,包括與契約數(shù)據(jù)相關(guān)聯(lián)的操作(添加、刪除或更新)判帮。契約可以是一個JSON模式局嘁、XML模式、一個對象晦墙,甚至是值驅(qū)動的消息(包含名稱-值對的映射消息)悦昵。對于更新,數(shù)據(jù)泵消息中包含的數(shù)據(jù)通常只包含新的數(shù)據(jù)值晌畅。例如但指,如果客戶更改了其概要文件中的電話號碼,則只會發(fā)送新的電話號碼以及客戶ID和更新數(shù)據(jù)的操作抗楔。
數(shù)據(jù)寫入器
數(shù)據(jù)寫入器組件接受來自數(shù)據(jù)泵的消息棋凳,并用數(shù)據(jù)泵消息中包含的信息更新數(shù)據(jù)庫(見圖15-7)。數(shù)據(jù)寫入器可以實現(xiàn)為服務(wù)连躏、應(yīng)用或數(shù)據(jù)中心(如Ab Initio)剩岳。數(shù)據(jù)寫入器的粒度可以根據(jù)數(shù)據(jù)泵和處理單元的范圍而變化。
基于領(lǐng)域的數(shù)據(jù)寫入器包含處理特定領(lǐng)域(如Customer)中的所有的更新所需的數(shù)據(jù)庫邏輯入热,而不管它接受的數(shù)據(jù)泵數(shù)量是多少拍棕。請注意在圖15-8中,有四個代表各自客戶領(lǐng)域(Profile勺良、WishList绰播、Wallet和Preferences)的不同處理單元和數(shù)據(jù)泵,但只有一個數(shù)據(jù)寫入器郑气。單個客戶數(shù)據(jù)寫入器監(jiān)聽所有四個數(shù)據(jù)泵幅垮,并包含必要的數(shù)據(jù)庫邏輯(如SQL),以更新數(shù)據(jù)庫中與客戶相關(guān)的數(shù)據(jù)。
或者忙芒,每類處理單元都可以有自己的專用數(shù)據(jù)寫入器組件示弓,如圖15-9所示。在這個模型中呵萨,數(shù)據(jù)寫入器專用于每個相應(yīng)的數(shù)據(jù)泵奏属,并且只包含特定處理單元(如錢包)的數(shù)據(jù)庫處理邏輯。雖然此模型往往會生成太多的數(shù)據(jù)寫入器組件潮峦,但由于處理單元囱皿、數(shù)據(jù)泵和數(shù)據(jù)寫入器的聯(lián)合,它確實提供了更好的可擴展性和靈活性忱嘹。
數(shù)據(jù)讀取器
數(shù)據(jù)寫入器負責(zé)更新數(shù)據(jù)庫嘱腥,而數(shù)據(jù)讀取器負責(zé)從數(shù)據(jù)庫中讀取數(shù)據(jù)并通過反向數(shù)據(jù)泵將其發(fā)送到處理單元。在基于空間的架構(gòu)中拘悦,只有在以下三種情況下才會調(diào)用數(shù)據(jù)讀取器:同一命名緩存的所有處理單元實例崩潰齿兔、同一命名緩存中所有處理單元的重新部署,或檢索復(fù)制緩存中未包含的存檔數(shù)據(jù)础米。在所有實例都停止運行的情況下(由于系統(tǒng)大面積崩潰或所有實例的重新部署)分苇,必須從數(shù)據(jù)庫中讀取數(shù)據(jù)(這在基于空間的架構(gòu)中通常是避免的)。
當(dāng)一類處理單元的實例開始啟動時屁桑,每個實例都試圖在緩存上獲取一個鎖医寿。第一個獲得鎖的成為臨時緩存所有者;其他人進入等待狀態(tài)蘑斧,直到鎖被釋放為止(這可能會因使用的緩存實現(xiàn)類型而異靖秩,但無論如何,在這種情況下竖瘾,緩存會有一個主所有者)盆偿。要加載緩存,獲得臨時緩存所有者狀態(tài)的實例將向請求數(shù)據(jù)的隊列發(fā)送消息准浴。數(shù)據(jù)讀取器組件接受讀取請求,然后執(zhí)行必要的數(shù)據(jù)庫查詢邏輯來檢索處理單元所需的數(shù)據(jù)捎稚。當(dāng)數(shù)據(jù)讀取器從數(shù)據(jù)庫中查詢數(shù)據(jù)時乐横,它將數(shù)據(jù)發(fā)送到另一個隊列(稱為反向數(shù)據(jù)泵)。臨時緩存所有者處理單元從反向數(shù)據(jù)泵接收數(shù)據(jù)并加載緩存今野。一旦加載了所有數(shù)據(jù)葡公,臨時所有者將釋放緩存上的鎖,然后所有其他實例將被同步条霜,這時候處理可以開始催什。該處理流程如圖15-10所示。
與數(shù)據(jù)寫入器類似宰睡,數(shù)據(jù)讀取器也可以基于領(lǐng)域或?qū)S糜谝粋€特定的處理單元類(通常也是這種形式)蒲凶。實現(xiàn)方式也與數(shù)據(jù)寫入器相同气筋,要么是服務(wù)、應(yīng)用或者數(shù)據(jù)中心旋圆。
數(shù)據(jù)寫入器和數(shù)據(jù)讀取器本質(zhì)上形成了通常所說的數(shù)據(jù)抽象層(在某些情況下是數(shù)據(jù)訪問層)宠默。兩者之間的區(qū)別在于處理單元對數(shù)據(jù)庫中表(或模式)結(jié)構(gòu)的詳細了解程度。數(shù)據(jù)訪問層意味著處理單元耦合到數(shù)據(jù)庫中的底層數(shù)據(jù)結(jié)構(gòu)灵巧,并且只使用數(shù)據(jù)讀寫器間接訪問數(shù)據(jù)庫搀矫。另一方面,數(shù)據(jù)抽象層意味著處理單元通過單獨的契約與底層數(shù)據(jù)庫表結(jié)構(gòu)解耦刻肄∪壳颍基于空間的架構(gòu)通常依賴于數(shù)據(jù)抽象層模型,因此每個處理單元中的復(fù)制緩存模式可以不同于底層數(shù)據(jù)庫表結(jié)構(gòu)敏弃。這允許對數(shù)據(jù)庫進行增量變更卦羡,而不對處理單元造成影響。為了促進這種增量變更权她,數(shù)據(jù)寫入器和數(shù)據(jù)讀取器包含轉(zhuǎn)換邏輯虹茶,以便在列類型更改、列或表被刪除時隅要,數(shù)據(jù)讀取器和數(shù)據(jù)編寫器可以緩沖數(shù)據(jù)庫變更蝴罪,直到可以對處理單元緩存進行必要的更改。
數(shù)據(jù)沖突
當(dāng)在活動/活動狀態(tài)下使用復(fù)制緩存時步清,其中包含相同命名緩存的任何服務(wù)實例都可能發(fā)生更新要门,而由于復(fù)制延遲,可能會發(fā)生數(shù)據(jù)沖突廓啊。當(dāng)在一個緩存實例(緩存A)中更新數(shù)據(jù)欢搜,并且在復(fù)制到另一個緩存實例(緩存B)的過程中,相同的數(shù)據(jù)被該緩存(緩存B)更新時谴轮,就會發(fā)生數(shù)據(jù)沖突炒瘟。在這種情況下,緩存B的本地更新將被來自緩存A的舊數(shù)據(jù)通過復(fù)制覆蓋第步,而通過復(fù)制疮装,緩存A中的相同數(shù)據(jù)將被來自緩存B的更新覆蓋。
為了說明這個問題粘都,假設(shè)有兩個服務(wù)實例(服務(wù)A和服務(wù)B)包含產(chǎn)品庫存的復(fù)制緩存廓推。下面的流程演示了數(shù)據(jù)沖突問題:
- 當(dāng)前藍色小裝置的庫存數(shù)量是500臺
- 服務(wù)A將藍色小裝置的庫存緩存更新到490臺(售出10臺)
- 在復(fù)制期間,服務(wù)B將藍色小裝置的庫存緩存更新到495個單元(售出5個)
- 由于從服務(wù)A更新進行復(fù)制翩隧,服務(wù)B緩存更新為490臺
- 由于從服務(wù)B更新進行復(fù)制樊展,服務(wù)A緩存將更新到495臺
- 服務(wù)A和B中的緩存都不正確且不同步(庫存應(yīng)為485臺)
有幾個因素會影響可能發(fā)生的數(shù)據(jù)沖突數(shù)量:包含相同緩存的處理單元實例的數(shù)量、緩存的更新速率、緩存大小专缠,最后是緩存產(chǎn)品的復(fù)制延遲時間雷酪。根據(jù)這些因素,用于確定可能發(fā)生多少潛在數(shù)據(jù)沖突的概率公式如下:
其中藤肢,N表示使用相同命名緩存的服務(wù)實例數(shù)太闺,UR表示更新速率(以毫秒為單位,取平方)嘁圈,S表示緩存大惺÷睢(根據(jù)行數(shù)來統(tǒng)計),RL表示緩存產(chǎn)品的復(fù)制延遲最住。
此公式對于確定可能發(fā)生的數(shù)據(jù)沖突百分比以及使用復(fù)制緩存的可行性非常有用钞澳。例如,考慮以下值作為此計算中涉及的系數(shù):
更新速率(UR):????20次/秒
實例數(shù)量(N):????5
緩存大姓歉俊(S):????50轧粟,000行
復(fù)制延遲(RL):????100毫秒
更新次數(shù):????72,000/小時
沖突概率:????14.4次/小時
百分比:????0.02%
將這些因素應(yīng)用到公式中脓魏,每小時可以得到72兰吟,000次更新,同一數(shù)據(jù)的14次更新很有可能發(fā)生沖突茂翔』彀考慮到百分比比較低(0.02%),復(fù)制將是一個可行的選擇珊燎。
不同的復(fù)制延遲對數(shù)據(jù)的一致性有很大的影響惭嚣。復(fù)制延遲取決于許多因素,包括網(wǎng)絡(luò)類型和處理單元之間的物理距離悔政。由于這個原因晚吞,復(fù)制延遲值很少在產(chǎn)品中注明,必須根據(jù)生產(chǎn)環(huán)境中的實際測量值進行計算和派生谋国。
如果實際的復(fù)制延遲(我們經(jīng)常用來確定數(shù)據(jù)沖突的數(shù)量)不可用槽地,那么前面示例中使用的值(100毫秒)是一個很好的規(guī)劃數(shù)。例如芦瘾,將復(fù)制延遲從100毫秒更改為1毫秒闷盔,會產(chǎn)生相同數(shù)量的更新(每小時72000次),但每小時只產(chǎn)生0.1次沖突的可能性旅急!該場景如下表所示:
更新速率(UR):????20次/秒
實例數(shù)量(N):????5
緩存大小(S):????50牡整,000行
復(fù)制延遲(RL):????1毫秒(從100變成)
更新次數(shù):????72藐吮,000/小時
沖突概率:????0.1次/小時
百分比:????0.0002%
包含相同命名緩存的處理單元數(shù)(通過實例數(shù)因子表示)也與可能發(fā)生的數(shù)據(jù)沖突數(shù)成正比。例如,將處理單元的數(shù)量從5個實例減少到2個實例谣辞,在每小時72000個更新中迫摔,數(shù)據(jù)沖突率僅為每小時6個:
更新速率(UR):????20次/秒
實例數(shù)量(N):????2(從5變成)
緩存大小(S):????50泥从,000行
復(fù)制延遲(RL):????100毫秒
更新次數(shù):????72句占,000/小時
沖突概率:????5.8次/小時
百分比:????0.008%
緩存大小是唯一與沖突率成反比的因素。當(dāng)緩存大小減小時躯嫉,沖突率增加纱烘。在我們的示例中,將緩存大小從50祈餐,000行減少到10擂啥,000行(并保持所有因素與第一個示例相同)的沖突率為每小時72,明顯高于50帆阳,000行的情況:
更新速率(UR):????20次/秒
實例數(shù)量(N):????5
緩存大胁负(S):????10,000行(從50蜒谤,000變成)
復(fù)制延遲(RL):????100毫秒
更新次數(shù):????72山宾,000/小時
沖突概率:????72次/小時
百分比:????0.1%
在正常情況下,大多數(shù)系統(tǒng)在一段長的時間內(nèi)沒有相同的更新速率(UR)鳍徽。因此资锰,當(dāng)使用此計算公式時,了解峰值使用期間的最大更新速率并計算最小旬盯、正常和峰值沖突率是很有幫助的台妆。
云端與內(nèi)部實現(xiàn)的對比
當(dāng)涉及到部署的環(huán)境時,基于空間的架構(gòu)提供了一些獨特的選擇胖翰。整個拓撲接剩,包括處理單元、虛擬化中間件萨咳、數(shù)據(jù)泵懊缺、數(shù)據(jù)讀取器和寫入器以及數(shù)據(jù)庫,都可以部署在基于云的環(huán)境和本地內(nèi)部環(huán)境培他。然而鹃两,這種架構(gòu)風(fēng)格也可以部署在這些環(huán)境之間,提供了一個其他架構(gòu)風(fēng)格所沒有的獨特功能舀凛。
這種架構(gòu)風(fēng)格的一個強大功能(如圖15-11所示)是通過處理單元和虛擬化中間件在托管云環(huán)境中部署應(yīng)用程序俊扳,同時保留物理數(shù)據(jù)庫和相應(yīng)的數(shù)據(jù)在本地環(huán)境。由于異步數(shù)據(jù)泵和這種架構(gòu)風(fēng)格的最終一致性模型猛遍,這種拓撲支持非常有效的基于云的數(shù)據(jù)同步馋记。事務(wù)處理可以在基于云的動態(tài)和彈性環(huán)境中進行号坡,同時在安全和本地內(nèi)部環(huán)境中保留物理數(shù)據(jù)管理、報告和數(shù)據(jù)分析梯醒。
復(fù)制緩存與分布式緩存對比
基于空間的架構(gòu)依賴于緩存來進行應(yīng)用程序的事務(wù)處理宽堆。消除對數(shù)據(jù)庫的直接讀寫需求是基于空間的架構(gòu)能夠支持高擴展性、高彈性和高性能的原因茸习⌒罅ィ基于空間的架構(gòu)主要依賴于復(fù)制緩存,但也可以使用分布式緩存号胚。
使用復(fù)制緩存籽慢,如圖15-12所示,每個處理單元都包含自己的內(nèi)存中數(shù)據(jù)網(wǎng)格涕刚,該網(wǎng)格在使用相同名稱緩存的所有處理單元之間同步嗡综。當(dāng)任何一個處理單元中的緩存發(fā)生更新時,其他處理單元將自動使用新的信息進行更新杜漠。
復(fù)制緩存不僅速度極快极景,而且還支持高級別的容錯性。由于沒有中央服務(wù)器持有緩存驾茴,所以復(fù)制緩存沒有單點故障的問題盼樟。但是,根據(jù)所使用的緩存產(chǎn)品的實現(xiàn)锈至,此規(guī)則可能會有例外晨缴。有些緩存產(chǎn)品需要有一個外部控制器來監(jiān)視和控制處理單元之間的數(shù)據(jù)復(fù)制,但是大多數(shù)產(chǎn)品公司都在放棄這種模式峡捡。
雖然復(fù)制緩存是基于空間的架構(gòu)的標準緩存模型击碗,但在某些情況下不可能使用復(fù)制緩存。這些情況包括大數(shù)據(jù)量(緩存大忻亲尽)和緩存數(shù)據(jù)的高更新速率稍途。由于每個處理單元使用的內(nèi)存過大,超過100MB的內(nèi)部內(nèi)存緩存可能會開始導(dǎo)致彈性和高可擴展性方面的問題砚婆。處理單元通常部署在虛擬機中(或者在某些情況下代表虛擬機)械拍。每個虛擬機只有一定數(shù)量的內(nèi)存可供內(nèi)部緩存使用,從而限制了可啟動以處理高吞吐量情況的處理單元實例的數(shù)量装盯。此外坷虑,如“數(shù)據(jù)沖突”一節(jié)所示,如果緩存數(shù)據(jù)的更新速率太高埂奈,數(shù)據(jù)網(wǎng)格可能無法跟上高更新速率迄损,以確保所有處理單元實例的數(shù)據(jù)一致性。當(dāng)出現(xiàn)這些情況時账磺,可以使用分布式緩存海蔽。
分布式緩存共屈,如圖15-13所示,需要一個外部服務(wù)器或服務(wù)來持有一個集中的緩存党窜。在這個模型中,處理單元不在內(nèi)存中存儲數(shù)據(jù)借宵,而是使用專有協(xié)議從中央緩存服務(wù)器訪問數(shù)據(jù)幌衣。分布式緩存支持高級別的數(shù)據(jù)一致性,因為數(shù)據(jù)都在一個位置壤玫,不需要復(fù)制父泳。但是吁津,此模型的性能低于復(fù)制緩存,因為緩存數(shù)據(jù)必須遠程訪問,這增加了系統(tǒng)的總體延遲冀值。容錯性也是分布式緩存的一個問題。如果包含數(shù)據(jù)的緩存服務(wù)器出現(xiàn)故障搁吓,則無法從任何處理單元訪問或更新任何數(shù)據(jù)各聘,使它們無法運行∷剩可以通過鏡像分布式緩存來減輕容錯性問題达址,但如果主緩存服務(wù)器意外停機,并且數(shù)據(jù)無法到達鏡像緩存服務(wù)器趁耗,則可能會出現(xiàn)一致性問題沉唠。
當(dāng)緩存的大小相對較小(小于100 MB)并且緩存的更新率足夠低苛败,以至于緩存產(chǎn)品的復(fù)制引擎能夠跟上緩存更新時满葛,使用復(fù)制緩存和分布式緩存之間的決策將變成數(shù)據(jù)一致性對比性能和容錯性的取舍。分布式緩存總是比復(fù)制緩存提供更好的數(shù)據(jù)一致性罢屈,因為數(shù)據(jù)緩存在一個位置(而不是分散在多個處理單元上)嘀韧。但是,使用復(fù)制緩存時儡遮,性能和容錯性總是更好乳蛾。很多時候,這個決定歸結(jié)為在處理單元中緩存的數(shù)據(jù)類型鄙币。對高度一致的數(shù)據(jù)的(如可用產(chǎn)品的庫存計數(shù))需要通常有必要使用分布式緩存肃叶,而不經(jīng)常更改的數(shù)據(jù)(如名稱/值對、產(chǎn)品代碼和產(chǎn)品描述等參考數(shù)據(jù))通常有必要使用一個復(fù)制緩存以進行快速查找十嘿。表15-1列出了一些選擇標準因惭,可作為選擇何時使用分布式緩存還是使用復(fù)制緩存的指引。
在選擇與基于空間的架構(gòu)一起使用的緩存模型類型時绩衷,請記住蹦魔,在大多數(shù)情況下激率,這兩種模型都適用于任何給定的應(yīng)用上下文。換句話說勿决,復(fù)制緩存和分布式緩存都不能解決所有問題乒躺。與其試圖通過一個橫跨整個應(yīng)用的單一的緩存模型尋找妥協(xié)方案,不如利用每一個模型的優(yōu)點低缩。例如嘉冒,對于維護當(dāng)前庫存的處理單元,選擇分布式緩存模型以實現(xiàn)數(shù)據(jù)一致性咆繁;對于維護客戶概要信息的處理單元讳推,選擇復(fù)制緩存以提高性能和容錯性。
“近緩存”考慮事項
近緩存是一種緩存混合模型玩般,它將內(nèi)存中的數(shù)據(jù)網(wǎng)格與分布式緩存連接起來银觅。在這個模型中(如圖15-14所示),分布式緩存被稱為全備份緩存(full backing cache)坏为,每個處理單元中包含的每個內(nèi)存中的數(shù)據(jù)網(wǎng)格被稱為前端緩存(front cache)究驴。前端緩存始終包含完整備份緩存的較小子集,它利用逐出策略刪除舊項目久脯,以便添加新的項目纳胧。前端緩存可以是包含最近使用項目的最近使用緩存(MRU),也可以是包含最常用項目的最常用緩存(MFU)帘撰∨苣剑或者,可以在前端緩存中使用隨機替換逐出策略摧找,以便在需要空間添加新項目時以隨機方式刪除舊項目核行。當(dāng)沒有明確的數(shù)據(jù)分析時,無論是最新使用的還是最頻繁使用的蹬耘,隨機替換(RR)是一個很好的逐出策略芝雪。
雖然前端緩存始終與全備份緩存保持同步,但每個處理單元中包含的前端緩存在共享相同數(shù)據(jù)的其他處理單元之間不同步综苔。這意味著共享同一數(shù)據(jù)上下文(如客戶概要信息)的多個處理單元在其前端緩存中可能有不同的數(shù)據(jù)惩系。這會導(dǎo)致處理單元之間的性能和響應(yīng)能力不一致,因為每個處理單元在前端緩存中包含不同的數(shù)據(jù)如筛。因此堡牡,我們不建議在基于空間的架構(gòu)中使用近緩存模型。
實施示例
基于空間的架構(gòu)非常適合于用戶或請求量劇增的應(yīng)用杨刨,以及吞吐量超過10晤柄,000個并發(fā)用戶的應(yīng)用⊙停基于空間的架構(gòu)的例子包括在線音樂會票務(wù)系統(tǒng)和在線拍賣系統(tǒng)等應(yīng)用芥颈。這兩個例子都需要高性能惠勒、高擴展性和高彈性。
音樂會票務(wù)系統(tǒng)
音樂會票務(wù)系統(tǒng)有一個獨特的問題:在一場流行音樂會宣布之前爬坑,并發(fā)用戶量相對較低纠屋。一旦音樂會門票開始銷售,用戶量通常會從幾百個并發(fā)用戶激增到幾千個(可能是上萬個盾计,具體取決于哪一場演唱會)巾遭,所有人都試圖獲得音樂會的門票(并希望是好的座位4彻馈)。門票通常在幾分鐘內(nèi)就會賣完吼和,這需要基于空間的架構(gòu)所支持的架構(gòu)特性來支持涨薪。
與這種系統(tǒng)相關(guān)的挑戰(zhàn)很多。首先炫乓,不管座位偏好如何刚夺,門票的數(shù)量是一定的∧┑罚考慮到大量并發(fā)請求侠姑,座位是否可以預(yù)定的信息必須不斷更新并且盡可能快地提供。另外箩做,假設(shè)指定座位是一個選項莽红,座位可用性也必須盡快更新。對于這種類型的系統(tǒng)邦邦,連續(xù)地同步訪問一個中央數(shù)據(jù)庫可能行不通安吁。對于一個典型的數(shù)據(jù)庫來說,在這種規(guī)模和更新頻率的水平上燃辖,通過標準數(shù)據(jù)庫事務(wù)來處理數(shù)以萬計的并發(fā)請求是非常困難的鬼店。
基于空間的體系結(jié)構(gòu)非常適合音樂會售票系統(tǒng),因為這種應(yīng)用需要高彈性黔龟。想要購買音樂會門票的并發(fā)用戶數(shù)量的瞬時增加會立即被部署管理器發(fā)現(xiàn)妇智,而部署管理器又會啟動大量的處理單元來處理大量的請求。最佳情況下氏身,部署管理器將被配置為在門票發(fā)售之前不久啟動所需數(shù)量的處理單元巍棱,因此在用戶負載顯著增加之前讓這些實例處于待命狀態(tài)。
在線拍賣系統(tǒng)
在線拍賣系統(tǒng)(對拍賣中的物品進行競價)與前面描述的在線音樂會票務(wù)系統(tǒng)具有相同的特性观谦,這兩個系統(tǒng)都需要高水平的性能和彈性拉盾,并且在用戶和請求負載方面都有不可預(yù)測的峰值。當(dāng)一場拍賣開始時豁状,沒有辦法確定有多少人將參加拍賣捉偏,以及這些人中倒得,每一個要價將有多少人同時出價。
基于空間的架構(gòu)非常適合這種類型的問題域夭禽,因為隨著負載的增加霞掺,可以啟動多個處理單元;隨著拍賣的結(jié)束讹躯,閑置的處理單元可能會被銷毀菩彬。每個拍賣都可以使用單獨的處理單元,以確保與投標數(shù)據(jù)的一致性潮梯。此外骗灶,由于數(shù)據(jù)泵的異步性質(zhì),投標數(shù)據(jù)可以在沒有太多延遲的情況下發(fā)送到其他單元處理(如投標歷史記錄秉馏、投標分析和審計)耙旦,從而提高投標過程的總體性能。
架構(gòu)特性評級
特性評級表中的一星級評級(如圖15-15所示)意味著特定的架構(gòu)特性在某種架構(gòu)中沒有得到很好的支持萝究,而五星評級意味著架構(gòu)特性是某種架構(gòu)風(fēng)格中最強大的特性之一免都。記分卡中確定的每個特性的定義見第4章。
請注意帆竹,基于空間的架構(gòu)最大限度地提高了彈性绕娘、可擴展性和性能(均為五星級)。這些是這種架構(gòu)風(fēng)格的驅(qū)動屬性和主要優(yōu)勢栽连。所有這三個架構(gòu)特性的高評級都是通過利用內(nèi)存中的數(shù)據(jù)緩存和刪除數(shù)據(jù)庫約束來實現(xiàn)的险领。因此,使用這種架構(gòu)風(fēng)格可以處理數(shù)百萬并發(fā)用戶升酣。
雖然高層次的彈性舷暮、可擴展性和性能是這種架構(gòu)風(fēng)格的優(yōu)勢,但這種優(yōu)勢特別是在總體的簡單性和可測試性方面需要作出權(quán)衡噩茄∠旅妫基于空間的架構(gòu)是一種非常復(fù)雜的架構(gòu)風(fēng)格,因為使用了緩存和主數(shù)據(jù)存儲的最終一致性绩聘。必須注意需要確保在這種架構(gòu)風(fēng)格的眾多移動部件中的任何一個發(fā)生崩潰時不會丟失數(shù)據(jù)(請參閱第14章中的“防止數(shù)據(jù)丟失”)沥割。
由于模擬這種架構(gòu)風(fēng)格所支持的高級別的可擴展性和彈性所涉及的復(fù)雜性,可測試性得到了一星級的評級凿菩。在峰值負載下測試成百上千的并發(fā)用戶是一項非常復(fù)雜和昂貴的任務(wù)机杜,因此,大多數(shù)高容量測試都是在實際極端負載的生產(chǎn)環(huán)境中進行的衅谷。這會對生產(chǎn)環(huán)境中的正常操作產(chǎn)生極大的風(fēng)險椒拗。
在選擇這種架構(gòu)風(fēng)格時,成本是另一個考慮因素∈纯粒基于空間的架構(gòu)的實現(xiàn)相對比較昂貴在验,主要是由于緩存產(chǎn)品的許可費,以及由于高可擴展性和彈性所需要的云端和本地內(nèi)部系統(tǒng)的高資源使用率堵未。
很難確定基于空間的架構(gòu)的分區(qū)類型腋舌,因此我們將其標識為既是領(lǐng)域分區(qū),也是技術(shù)分區(qū)渗蟹】榻龋基于空間的架構(gòu)是按領(lǐng)域劃分的,這不僅是因為它與特定類型的領(lǐng)域(高彈性和可擴展的系統(tǒng))保持一致雌芽,而且還因為處理單元的靈活性授艰。處理單元可以扮演領(lǐng)域服務(wù),與基于服務(wù)的架構(gòu)和微服務(wù)架構(gòu)中所定義的服務(wù)一樣的方式世落。同時想诅,基于空間的架構(gòu)是按技術(shù)劃分的,它通過數(shù)據(jù)泵將使用緩存的事務(wù)處理與數(shù)據(jù)庫中數(shù)據(jù)的實際存儲分離開來岛心。在如何處理請求方面,處理單元篮灼、數(shù)據(jù)泵忘古、數(shù)據(jù)讀取器和寫入器以及數(shù)據(jù)庫都形成了一個技術(shù)層,與如何構(gòu)造單體n層(分層)架構(gòu)方面非常相似诅诱。
基于空間的架構(gòu)中的量子數(shù)可以根據(jù)用戶界面的設(shè)計方式以及處理單元之間的通信方式而變化髓堪。因為處理單元不與數(shù)據(jù)庫同步通信,所以數(shù)據(jù)庫本身不是量子方程的一部分娘荡。因此干旁,基于空間的架構(gòu)中的量子通常是通過各種用戶接口和處理單元之間的關(guān)聯(lián)來描繪的。彼此同步通信的處理單元(或通過編排的處理網(wǎng)格同步通信)都將是同一個架構(gòu)量子的一部分炮沐。