當前位置:首頁 » 文件管理 » 電商緩存方案

電商緩存方案

發布時間: 2022-09-27 16:41:52

1. 網站哪些內容適合用CDN技術

網站哪些內容都可以使用CDN技術的。
CDN即內容分發網路,是構建在現有網路基礎之上的智能虛擬網路,CDN加速原理是用戶首次請求到CDN節點,CDN節點未命中向源站獲取文件,源站根據請求響應內容給CDN節點,同時CDN節點緩存內容,CDN節點將內容響應給終端用戶,當同一CDN節點內的用戶再次訪問時,CDN便會直接將緩存內容返回給用戶,讓用戶就近獲取所需內容,降低網路擁塞,提高用戶訪問響應速度和命中率。CDN加速功能雖然用域廣泛,但並不是任何互聯網產品都適用,考慮到加速的效果和運營成本,整理出推薦適用CDN加速的七類網站內容。
一. 靜態資源加速
著互聯網開發和迭代速度越來越快,我們訪問的網站也變得越來越龐大,一般的企業官網以及各類展示型網站的伺服器上都存儲了大量靜態資源,當較多用戶訪問我們的網站請求JS、CSS、圖片等靜態資源時,高並發量增加源站了壓力,造成訪問網路擁堵,導致我們的網站變慢卡頓。若把我們的靜態資源緩存到CDN節點上,訪問網站的用戶直接請求到就近CDN節點,CDN節點向用戶分發傳輸相關庫的靜態資源文件,這樣就可以降低網站自身伺服器的請求壓力,提高了網站的訪問速度和用戶體驗。
二. 動態資源加速
如今我們的互聯網產品需求功能化要求巨大,我們的動態產品越來越多,交互性的動態網頁如用戶注冊、信息發布、產品展示、訂單管理等網站,動態網站大大節省工作量,無須手動的自動更新,因時因人而變,不同時間、不同用戶訪問同一網址時會出現不同頁面等需求功能。動態資源實時性,交互性需求量更大,CDN加速系統中的核心伺服器與DNS技術相結合,實時監控網路環境變化,監控各地網路延遲,有效避開網路瓶頸及擁堵環節,提高數據在源站與互聯網終端用戶之間傳輸的穩定及高效性,保障各種動態數據能夠及時傳遞到終端,提高頁面載入速度及頁面展現質量。
三. 音頻/視頻加速
這個時代音樂,直播,小視頻,電影,電視,填滿了我們的碎片時光,大部分人生活離不開音頻/視頻,高質的用戶體驗要求音頻/視頻要扛得起夜晚高峰期的百萬高並發,呈現的依然是穩定高清音畫質,並且保證隱私信號傳輸的全程加密,CDN的HTTP/HTTPS音/視頻點播加速服務通過將音頻/視頻文件快速分層同步傳輸到加速節點上,當最終用戶訪問時將其對網站的請求定向到離用戶最近的節點上,為用戶提供穩定可靠高質的HTTP/HTTPS音頻/視頻聽覺視覺服務。
四. 圖片加速
普通人常用的圖片站一般為素材圖片網站,漫畫壁紙圖片站,圖片拼圖工具網站,圖片在線交易平台等,為個人及企業提供所需圖片素材搜索,圖片觀看,高清圖片下載等服務,例如漫畫和電商平台上每天都會有大量商品圖片的查詢更新請求,高峰情況下每天有千萬級甚至億級的圖片,CDN系統使網路和客戶源文件伺服器形成良好的互動,即將源站的圖片(jpg,jpeg,png,gif,bmp等各種格式)、flash動畫、css/js、及各種文件類型的圖片緩存到節點上,無需服務端改造,能夠使整體圖片流量帶寬下降30%~40%,實現各地用戶實時快速訪問刷新獲取網站圖片。
五. 下載加速
工具APP下載是我們現代人最基礎手機的使用習慣,網路軟體、殺毒軟體、聊天工具、系統工具、媒體播放、輸入法、手機主題和驅動等豐富的綠色軟體等軟體的全網下載需求促使軟體開發商們及軟體下載站需要提供安全、綠色、快速,是國內專業的下載環境,CDN下載加速就能為用戶創造高速加密的下載場景,CDN下載分發加速,針對安裝包獲取、手機ROM升級、應用程序包下載等業務場景,提供穩定、優質的下載加速,具備突發性超大流量承載能力。利用多級緩存收斂及資源預熱,緩解源站壓力,讓用戶獲得極速的下載體驗。
六. 海外加速
全球互聯產生的跨境電商,海外游戲,國外網站,讓文化物品跨越物理距離來到全人類面前。物理上的距離讓數據傳輸在高並發時期速度緩慢,致使海外用戶體驗感較差,針對部分海外運營商存在國際出口投入大、業務成本高;基礎設施不完善,網路穩定性低;缺乏技術人才,運營能力差;大量訪問用戶訴求難以解決等問題,CDN依託遍及全球加速節點資源豐富,500+中國大陸境外加速,利用底層服務商自研的智能全球調度體系和質量實時監控系統,精準調度境外用戶請求,提供靜態外文網站、跨境電商圖片網站,游戲APP下載、音視頻等多種加速業務及整體解決方案。CDN能有效降低跨境訪問延遲,提升服務可用性,支持全球業務無縫出海。
七. 安全加速
我們使用的大多數網站APP的設計開發,只考慮到展示和正常用戶穩定使用,對於看不見的網站安全並沒有太多重視。互聯網經濟的興起,出於惡性商業競爭、敲詐勒索等原因,1999年開始一些企業網站受到DDOS,CC攻擊,雅虎是當時最著名的受害者,近年來隨著攻擊成本越來越低、效果特別明顯等特點,DDOS,CC攻擊已經演變成全球性網路安全威脅。攻擊者藉助代理伺服器向受害主機發送大量的合法請求,導致受害網站資料庫壓力就越大,被訪問的頻率也越高,佔用大量的系統資源導致網站打開緩慢或者無法訪問。眾所周知DDOS攻擊主要針對的是IP,所以隱藏源站IP就顯得十分重要,CDN 服務將網站訪問流量分配到了各個節點中,這樣一方面隱藏網站的真實IP,另一方面即使遭遇 DDOS攻擊,也可以將流量分散到各個節點中,防止源站崩潰,從而起到防禦的作用,為網站APP做好防護。

2. 不就是一個訂票網站嗎 12306 的核心模型設計思路究竟復雜在哪裡

本文的重點不是在如何解決高並發的問題,而是希望從業務角度去分析,12306 的理想模型應該是怎麼樣的。網上目前談 12306 的文章貌似都是千篇一律的只談技術,不談業務分析和如何建模的。所以我想寫一下自己的設計和大家交流學習。

1、需求概述

12306 這個系統,核心要解決的問題是網上售票。涉及到 2 個角色使用該系統:用戶、鐵道部。用戶的核心訴求是查詢余票、購票;鐵道部的核心訴求是售票。購票和售票其實是一個場景,對用戶來說是購票,對鐵道部來說是售票。因此,我們要設計一個在線的網站系統,解決用戶的查詢余票、購票,以及鐵道部的售票這 3 個核心訴求。看起來,這 3 個場景都是圍繞火車票展開的。

查詢余票:用戶輸入出發地、目的地、出發日三個條件,查詢可能存在的車次,用戶可以看到每個車次經過的站點名稱,以及每種座位的余票數量。

購票:購票分為訂票和付款兩個階段,本文重點分析訂票的模型設計和實現思路。

其實還有很多其他的需求,比如給不同的車次設定銷售座位數配額,以及不同的區段設置不同的限額。但相比前面兩個需求來說,我覺得這個需求相對次要一些。

2、需求分析

確實,12306 也是一個電商系統,而且看起來商品就是票了。因為如果把一張票看成是一個商品,那購票就類似於購買商品,然後每張票都有庫存,商品也有庫存的概念。但是如果我們仔細想想,會發現 12306 要復雜很多,因為我們無法預先確定好所有的票,如果非要確定,那隻能通過窮舉法了。

我們以北京西到深圳北的 G71 車次高鐵為例(這里只考慮南下的方向,不考慮深圳北到北京西的,那是另外一個車次,叫 G72),它有 17 個站(北京西是 01號站,深圳北是 17號站),3 種座位(商務、一等、二等)。表面看起來,這不就是 3 個商品嗎?G71 商務座、G71 一等座、G71 二等座。大部分輕易噴 12306 的技術人員(包括某些中等規模公司的專家、CTO)就是在這里栽第一個跟頭的。實際上,G71 有 136*3=408 種商品(408 個 SKU),怎麼算來的?如下:

如果賣北京西始發的,有 16 種賣法(因為後面有 16 個站),北京西到:保定、石家莊、鄭州、武漢、長沙、廣州、虎門、深圳。。。。都是一個獨立的商品,同理,石家莊上車的,有 15 種下車的可能,以此類推,單以上下車的站來計算,有 136 種票:16+15+14....+2+1=136。每種票都有 3 種座位,一共是 408 個商品。

為了方便後面的討論,我們先明確一下票是什麼?

一張票的核心信息包括:出發時間、出發地、目的地、車次、座位號。持有票的人就擁有了一個憑證,該憑證表示持有它的人可以坐某個車次的某個座位號,從某地到某地。所以,一張票,對用戶來說是一個憑證,對鐵道部來說是一個承諾;那對系統來說是什麼呢?不知道。這就是我們要分析業務,領域建模的原因,我們再繼續思考吧。

明白了票的核心信息後,我們再看看 G71 這個車次的高鐵,可以賣多少張票?

討論前先說明一下,一輛火車的物理座位數(站票也可以看成是一種座位,因為站票也有數量配額)不等於可用的最大配合。所有的物理座位不可能都通過 12306 網站來銷售,而是只會銷售一部分,比如 40%。其餘的還是會通過線下的方式銷售。不僅如此,可能有些站點上車的人會比較多,有些比較少,所以我們還會給不同的區間配置不同的限額。

比如 D31 北京南至上海共有 765 張,北京南有 260 張,楊柳青有 80 張,泰安有 76 張。如果楊柳青的 80 張票售完就會顯示無票,就算其他站有票也會顯示無票的。每個車次肯定會有各種座位的配額和限額的配置的,這種配置我目前無法預料,但我已經把這些規則都封裝近車次聚合根里了,所有的配置策略都是基於座位類型、站點、區間配置的。關於票的配置抽象出來,我覺得主要有 3 種:

某個區段最多允許出多少張;

某個區段最少允許出多少張;

某個站點上車的最多多少張。

當用戶訂票時,把用戶指定的區段和這 3 種配置條件進行比較,3 個條件都滿足,則可以出票。不滿足,則認為無票了。下面舉個例子:

ABCDEFG,這是所有站點。座位總配額是 100,假設 B 站點上車,E 站下車的人比較少,那我們就可以設定 BE 這個區段最多隻能出 10 張票。所以,只要是用戶的訂票是在這個區段內的,就最多出 10 張。再比如,一列車次,總共 100 個座位配額,希望全程票最少滿足 80 張,那我們只要給 AG 這個區段設定最少 80 張。那任何訂票請求,如果是子區間的,就不能超過 100-80,即 20 張。這兩種條件必須同時滿足,才允許出票。

但是,不管如何做配額和限額,我們總是針對某個車次進行配置,這些配置只是車次內部售票時的一些額外的判斷條件(業務規則),不影響車次模型的核心地位和對外暴露的功能。所以,為了本文討論的清楚起見,我後續的討論都不涉及配額和限額的問題,而是認為任何區段都可以享受火車最大的物理座位數。

並且,為了討論問題方便,我們減少一些站點來討論。假設某個車次有 A,B,C,D 四個站點。那 001 這個人購買了 A,B 這個區間,系統會分配給 001 一個座位 x;但是因為 001 坐到 B 站點後會下車,所以相當於 x 這個座位又空出來了,也就是說,從 B 站點開始,系統又可以認為 x 這個座位是可用的。所以,我們得出結論:同一個座位,其實可以同時出售 AB,BC 這兩張票。通過這個簡單的分析,我們知道,一列火車雖然只有有限的座位數,比如 1000 個座位。但可以賣出的票遠遠不止 1000 個。

還是以 A,B,C,D 四個站點為例,假如火車總共有 1000 個座位,那 AB 可以賣 1000 張,BC 也可以賣 1000 張,同樣,CD 也可以賣 1000 張。也就是說,理論上最多可以賣出 3000 張票。但是如果換一種賣法,所有人都是買 ABCD 的票,也就是說所有的票都是經過所有站點的,那就是最多隻能賣出 1000 張票了。而實際的場景,一定是介於 1000 到 3000 之間。然後實際的 G71 這個車次,有 17 個站,那到底可以賣出多少個票,大家應該可以算了吧。理論上這 17 個站中的任意兩個站點之間所形成的線段,都可以出售為一張票。我數學不好,算不太清楚,麻煩有數學好的人幫我算算,呵呵。

通過上面的分析,我們知道一張票的本質是某個車次的某一段區間(一條線段),這個區間包含了若干個站點。然後我們還發現,只要區間不重疊,那座位就不會發生競爭,可以被回收利用,也就是說,可以同時預先出售。

另外,經過更深入的分析,我們還發現區間有 4 種關系:

不重疊;

部分重疊;

完全重疊;

覆蓋。

不重疊的情況我們已經討論過了,而覆蓋也是重疊的一種。所以我們發現如果重疊,比如有兩個區間發生重疊,那重疊部分的區間(可能誇一個或多個站點)是在爭搶座位的。因為假設一列火車有 100 個座位,那每個原子區間(兩個相鄰站點的連線),最多允許重疊 99 次。

所以,經過上面的分析,我們知道了一個車次能夠出售一張車票的核心業務規則是什麼?就是:這張車票所包含的每個原子區間的重疊次數加 1 都不能超過車次的總座位數,實際上重疊次數 +1 也可以理解為線段的厚度。

3、模型設計

上面我分析了一下票的本質是什麼。那接下來我們再來看看怎麼設計模型,來快速實現購票的需求,重點是怎麼設計商品聚合以及減庫存的邏輯。

傳統電商的思路

如果按照普通電商的思路,把票(站點區間)設計為商品(聚合根),然後為票設計庫存數量。我個人覺得是很糟糕的。因為一方面這種聚合根非常多(上面的 G71 就有 408 個);另一方面,即便枚舉出來了,一次購票也一定會影響非常多其他聚合根的庫存數量(只要被部分或全部重疊的區間都受影響)。這樣的一次訂單處理的復雜度是難以評估的。而且這么多聚合根的更新要在一個事務里,這不是為難資料庫嗎?而且,這種設計必然帶來大量的事務的並發沖突,很可能導致資料庫死鎖。

總之,我認為這種是典型的由於領域模型的設計錯誤,導致並發沖突高、數據持久化落地困難。或者如果要解決並發問題,只能排隊單線程處理,但是仍然解決不了要在一個事務里修改大量聚合根的尷尬局面。

聽說 12306 是採用了 Pivotal Gemfire 這種高大上的內存資料庫,我對這個不太了解。我不可想像要是不使用內存資料庫,他們要怎麼實現車次內的票之間的數據強一致性(就是保證所有出售的票都是符合上面討論的業務規則的)?所以,這種設計,我個人認為是思維定勢了,把火車票看成是普通電商的商品來看待。所以,我們有時做設計又要依賴於經驗,又要不能被以往經驗所束縛,真的不容易,關鍵還是要根據具體的業務場景多多深入分析,盡量分析抽象出問題的本質出來,這樣才能對症下葯。那是否有其他的設計思路呢?

我的思路

1、聚合設計

通過上面的分析我們知道,其實任何一次購票都是針對某個車次的,我認為車次是負責處理訂票的聚合根。我們看看一個車次包含了哪些信息?一個車次包括了:

車次名稱,如 G71;

座位數,實際座位數會分類型,比如商務座 20 個,一等座 200 個;二等座 500 個;我們這里為了簡化問題,可以暫時忽略類型,我認為這個類型不影響核心的模型的設計決策。需要格外注意的是:這里的座位數不要理解為真實的物理座位數,很有可能比真實的座位數要少。因為我們不可能把一個車次的所有座位都在網上通過 12306 來出售,而是只出售一部分,具體出售多少,要由工作人員人工指定。

經過的站點信息(包括站點的 ID、站點名稱等),注意:車次還會記錄這些站點之間的順序關系;

出發時間;看過 GRASP 九大模式中的信息專家模式的同學應該知道,將職責分配給擁有執行該職責所需信息的類。

我們這個場景,車次具有一次出票的所有信息,所以我們應該把出票的職責交給車次。另外學過 DDD 的同學應該知道,聚合設計有一個原則,就是:聚合內強一致性,聚合之間最終一致性。經過上面的分析,我們知道要產生一張票,其實要影響很多和這個票對應的線段相交的其他票的可用數量。因為所有的站點信息都在車次聚合內部,所以車次聚合內部自然可以維護所有的原子區間,以及每個原子區間的可用票數(相當於是庫存數)。當一個原子區間的可用票數為 0 的時候,意味著火車針對這個區間的票已經賣完了。所以,我們完全可以讓車次這個聚合根來保證出票時對所有原子區間的可用票數的更新的強一致性。對於車次聚合根來說,這很簡單,因為只是幾次簡單的內存操作而已,耗時可以忽略。一列火車假如有 ABCD 四個站點,那原子區間就是 3 個。對於 G71,則是 16 個。

2、怎麼判斷是否能出票?

基於上面的聚合設計,出票時扣減庫存的邏輯是:

根據訂單信息,拿到出發地和目的地,然後獲取這段區間里的所有的原子區間。然後嘗試將每個原子區間的可用票數減 1,如果所有的原子區間都夠減,則購票成功;否則購票失敗,提示用戶該票已經賣完了。是不是很簡單呢?知道了出票的邏輯,那退票的邏輯也就很簡單了,就是把這個票的所有原子區間的可用票數加 1 就 OK 了。如果我們從線段的厚度的角度去考慮,那出票時,每個原子區間的厚度就是 +1,退票時就是減一。就是相反的操作,但本質是一樣的。

所以,通過這樣的思路,我們將一次訂票的處理控制在了一個聚合根里,用聚合根內的強一致性的特性保證了訂票處理的強一致性,同時也保證了性能,免去了並發沖突的可能性。傳統電商那種把票單做類似商品的核心聚合根的設計,我當時第一眼看到就覺得不妥。因為這違背了 DDD 強調的強一致性應該由聚合根來保證、聚合根之間的最終一致性通過 Saga 來保證的原則。

還有一個很重要的概念我想說一下我的看法,就是座位和區間的關系。因為有些朋友和我講,考慮座位號的問題,雖然都能減 1,座位號也必須是同一個。我覺得座位是全局共享的,和區段無關(也許我的理解完全有誤,請大家指正)。座位是一個物理概念,一個用戶成功購買了一張票後,座位就會少一個,一張票唯一對應一個座位,但是一個座位有可能會對應多張票;而區間是一個邏輯上的概念,區間的作用有兩個:1)表示票的出發地和目的地;2)記錄票的可用數額。如果區間能連通(即該區間內的每個原子區間的可用數額都大於 0),則表示允許擁有一個座位。所以,我覺得座位和票(區間)是兩個維度的概念。

3、如何為票分配座位?

我覺得車次聚合根內部應該維護所有該車次已經售出的票,已經出售的票的的本質是區間和座位的對應關系。系統處理訂票時,用戶提交過來的是一段區間。所以,系統應該做兩個事情:

先根據區間去判斷是否有可用的座位;

如果有可用座位,則再通過演算法去選擇一個可用的座位;

當得到一個可用座位後,就可以生成一張票了,然後保存這個票到車次聚合根內部即可。下面舉個例子:

假設現在的情況是座位有 3 個,站點有 4 個:

座位:1,2,3

站點:abcd

票的賣法 1:

票 1:ab,1

票 2:bc,2

票 3:cd,3

票 4:ac,3

票 5:bd,1

這種選座位的方式應該比較高效,因為總是優先從座位池裡去拿座位,只有在萬不得已的時候才會去回收可重復利用的票。

上面的 4,5 兩個票,就是考慮回收利用的結果。

票的賣法 2:

票 1:ab,1

票 2:bc,1

票 3:cd,1

票 4:ac,2

票 5:bd,3

這種選座位的方式應該相對低效,因為總是優先會去掃描是否有可回收的座位,而掃描相對直接從座位池裡去拿票總是成本相對要高的。

上面的 2,3 兩個票,就是考慮回收利用的結果。

但是,優先從座位池裡拿票的演算法有缺陷,就是會出現雖然第一步判斷認為有可用的座位,但是這個座位可能不是全程都是同一個座位。舉例:

假設現在的情況是座位有 3 個,站點有 4 個:

座位:1,2,3

站點:abcd

票的賣法 3:

票 1:ab,1

票 2:bc,2

票 3:cd,3

現在如果有人要買 ad 的票,那可用的座位有 2,或者 3。但是無論是 2 還是 3,都要這個乘客中途換車位。比如賣給他座位 2,那他 ab 是坐的座位 2,但是 bc 的時候要坐座位 1 的。否則拿票 2 的那個人上車時,發現座位 2 已經有人了。而通過優先回收利用的演算法,是沒這個問題的。

所以,從上面的分析我們也知道選座位的演算法該怎麼寫了,就是採用優先回收利用座位的演算法。我認為不管我們這里怎麼設計演算法,都不影響大局,因為這一切都只發生在車次聚合根內部,這就是預先設計好聚合根,明確出票職責在哪個對象上的好處。

4、模型分析總結

我認為票不是核心聚合根,票只是一次出票的結果,一個憑證而已。

12306 真正的核心聚合根應該是車次,車次具有出票的職責,一次出票具體做的事情有:

判斷是否可出票;

選擇可用的座位;

更新一次出票時所有原子區間的可用票數,用於判斷下次是否能出票;

維護所有已售出的票,用於為選擇可用座位提供依據。

通過這樣的模型設計,我們可以確保一次出票處理只會在一個車次聚合根內進行。這樣的好處是:

不需要依賴資料庫事務就能實現數據修改的強一致性,因為所有修改只在一個聚合根內發生;

在保證數據強一致性的同時還能提供很高的並發處理能力,具體設計見下面的架構設計。

4、架構設計

我覺得 12306 這樣的業務場景,非常適合使用 CQRS 架構;因為首先它是一個查多寫少、但是寫的業務邏輯非常復雜的系統。所以,非常適合做架構層面的讀寫分離,即採用 CQRS 架構。而且應該使用數據存儲也分離的 CQRS。這樣 CQ 兩端才可以完全不需要顧及對方的問題,各自優化自己的問題即可。我們可以在 C 端使用 DDD 領域模型的思路,用良好設計的領域模型實現復雜的業務規則和業務邏輯。而 Q 端則使用分布式緩存方案,實現可伸縮的查詢能力。

1、訂票的實現思路

同時藉助像 ENode 這樣的框架,我們可以實現 in-memory + Event Sourcing 的架構。Event Sourcing 技術,可以讓領域模型的所有狀態修改的持久化統一起來,本來要用 ORM 的方式保存聚合根最新狀態的,現在只需要簡單的通用的方式保存一個事件即可(一次訂票只涉及一個車次聚合根的修改,修改只產生一個事件,只需要持久化一個事件(一個 JSON 串)即可,保證了高性能,無須依賴事務,而且通過 ENode 可以解決並發問題)。

我們只要保存了聚合根每次變化的事件(事件的結構怎麼設計,本文不做多的介紹了,大家可以思考下),就相當於保存了聚合根的最新狀態。而正是由於 Event Sourcing 技術的引入,讓我們的模型可以一直存活在內存中,即可以使用 in-memory 技術。不要小看 in-memory 技術,in-memory 技術在某些方面對提高命令的處理性能非常有幫助。

比如就以我們車次聚合根處理出票的邏輯,假設某個車次有大量的命令發送到分布式消息隊列,然後有一台機器訂閱了這個隊列的消息,然後這台機器處理這個車次的訂票命令時,由於這個車次聚合根一直在內存,所以就省去了每次要去資料庫取出聚合根的步驟,相當於少了一次資料庫 IO。

這樣的好處是,因為一個車次能夠真正出售的票是有限的,因為座位就那麼幾個,比如就 1000 個座位,估計一般正常情況也就出個 2000 個左右的票吧(具體能出多少張票要取決於區間的相交程度,上面分析過)。也就是說,這個聚合根只會產生 2000 個事件,也就是說只會有 2000 個訂票命令的處理是會產生事件,並持久化事件;而其餘的大量命令,因為車次在內存計算後發現沒有餘票了,就不會做任何修改,也不會產生領域事件,這樣就可以直接處理下一個訂票命令了。這樣就可以大大提高處理訂票命令的性能。

另外一個問題我覺得還需要提一下,因為用戶訂票成功後,還需要付款。但用戶有可能不去付款或者沒有在規定的時間內完成付款。那這種情況下,系統會自動釋放該用戶之前訂購的票。所以基於這樣的需求,我們在業務上需要支持業務級別的 2pc。即先預扣庫存,也就是先佔住這張票一定時間(比如 15 分鍾),然後付款成功後再真實給你這張票,系統做真正的庫存修改。

通過這樣的預扣處理,可以保證不會出現超賣的情況。這個思路其實和傳統電商比如淘寶這樣的系統類似,我就不多展開了,我之前寫的 Conference 案例也是這樣的思路,大家有興趣的可以去看一下我之前錄制的視頻。

2、查詢余票的實現思路

我覺得余票的查詢的實現相對簡單。雖然對於 12306 來說,查詢的請求佔了 80%,提交訂單的請求只佔 20%。但查詢由於對數據沒有修改,所以我們完全可以使用分布式緩存來實現。我們只需要精心設計好緩存的 key 即可;緩存 key 的多少要看成本,如果所有可能的查詢都設計對應的 key,那時間復雜度為 1,查詢性能自然高;但代價也大,因為 key 多了。如果想 key 少一點,那查詢的復雜度自然要上去一點。所以緩存設計無非就是空間換時間的思路。然後,緩存的更新無非就是:自動失效、定時更新、主動通知 3 種。通過 CQRS 架構,由於 CQ 兩端是事件驅動的,當 C 端有任何狀態變化,都會產生對應的事件去通知 Q 端,所以我們幾乎可以做到 Q 端的准實時更新。

同時由於 CQ 兩端的完全解耦,Q 端我們可以設計多種存儲,如資料庫和緩存(Redis 等);資料庫用於線下維護關系型數據,緩存用戶實時查詢。資料庫和緩存的更新速度相互不受影響,因為是並行的。對同一個事件,可以 10 台機器負責更新緩存,100 台機器負責更新資料庫。即便資料庫的更新很慢,也不會影響緩存的更新進度。這就是 CQRS 架構的好處,CQ 的架構完全不同,且我們隨時可以重建一種新的 Q 端存儲。不知道大家體會到了沒有?

關於緩存 key 的設計,我覺得主要從查詢余票時傳遞的信息來考慮。12306 的關鍵查詢是:出發地、目的地、出發日期三個信息。我覺得有兩種 key 的設計思路:

直接設計了該查詢條件的 key,然後快速拿到車次信息,直接返回;這種方式就是要求我們系統已經枚舉了所有車次的所有可能出現的票(區間)的緩存 key,相信你一定知道這樣的 key 是非常多的。

不是枚舉所有區間,而是把每個車次的每個原子區間(相鄰的兩個站點所連成的直線)的可用票數作為 key。這樣,key 就非常少了,因為車次假如有 10000 個,然後每個車次平均 15 個區間,那也就 15W 個 key 而已。當我們要查詢時,只需要把用戶輸入的出發地和目的地之間的所有原子區間的可用票數都查出來,然後比較出最小可用票數的那個原子區間。則這個原子區間的可用票數就是用戶輸入的區間的可用票數了。當然,到這里我提到考慮出發日期。我認為出發日期是用來決定具體是哪個車次聚合根的。同一個車次,不同的日期,對應的聚合根實例是不同的,即便是同一天,也可能有多個車次聚合根,因為有些車次一天有幾班的,比如上午 9 點發車的一班,下午 3 點發車的一般。所以,我們也只要把日期也作為緩存 key 的一部分即可。

總結

本文完全是憑自己對 12306 這個網站的核心業務的簡單思考而得到的一些設計結果。如果真正的 DDD 領域建模,更多的是要和業務一線的工作人員、領域專家進行深入溝通,才能更深入的了解該領域內的業務知識,從而才能設計出更靠譜的領域模型和架構設計。

非常慚愧,我沒有上 12306 買過火車票,家離的比較近,就算要買也是家人給我買:)所以,本文所分享的內容難免是紙上談兵。但我覺得 12306 這個系統的業務確實比傳統的電商系統要復雜,且並發又這么高。所以,我覺得這個系統真的很值得大家重視模型的設計,而不只是只關注技術層面的實現。

3. 假設自己是一名電商網站的負責人,請寫出網站未來五年的發展規劃

一、小型電商網站的架構

剛從傳統軟體行業進入到電商企業時,覺得電商網站沒有什麼技術含量,也沒有什麼門檻,都是一些現有的東西堆積木似的堆出來罷了。然而,真正進入到這個行業之後,才發現並非如此。有人說過,好的架構,是演化出來的,電商網站的架構也是如此。現在好的電商網站,看似很復雜,很牛逼,其實也是從很小的架構,也是從沒什麼技術含量開始的。所以,架構的演化過程,就是在技術團隊不斷追求極致的過程。

今天就來總結小型電商網站的架構演進。一套電商系統最初期的架構,往往會採用一個比較典型的LAMP架構,前端加上Apache/php,後端是MySQL。這個算是比較流行的。不過,目前還有一套.net的技術架構,可能大家很少提到。很不幸,我就是在一個.net平台為基礎的電商公司。所以,今天也是要總結.net 平台的電商架構。

1技術架構

如何打造一個小而精的電商網站架構
一般初期的電商網站,基本就幾個業務子系統:網站前台、商家前台、系統管理後台、App、M站等。業務量也不是很大。所以,MVC + 緩存 + 資料庫基本就搞定了。

單就開發效率而言,.net MVC 的技術架構不會比LAMP開發速度慢。所以,一些企業,為了快速推出自己的電商平台,也會採用.net 架構。

2基礎架構

如何打造一個小而精的電商網站架構
上圖為基礎架構層面。這是一個很簡單的基礎架構。

前端網站和M站,考慮到訪問量和系統的可用性,基本會採用分布式部署。通過代理伺服器進行請求分發。
其它的業務子系統,像商家前台和管理系統,基本上都是單機或是主從部署。
各個DB ,Redis 服務和文件和圖片服務,搜索引擎Solr服務等,採用主從部署。
3詳細架構

如何打造一個小而精的電商網站架構
整個系統架構裡面,還有一個比較重要的組成部分,那就是監控系統。例如:流量監控、硬體監控、系統性能監控等, 還有就是對某個頁面進行監控,設置頁面的其中一塊進行監控等。它是提高整個平台可用性的一個重要手段。多平台、多個維度的監控,能夠確保系統的可用性。一旦出現異常,特別在硬體或者性能方面出現異常,監控系統也能立刻發出警告,這樣也好防範於未然。

總而言之,一個好的系統架構應該從擴展性、安全性、性能和可靠性來考慮。羅馬不是一天建成的,架構適合就行,可以先行之而後優。通過漸進演化的過程,逐步讓系統越來越完善。

二、日誌與監控系統的解決方案

監控系統主要用於伺服器集群的資源和性能監控,以及應用異常、性能監控、日誌管理等多維度的性能監控分析。一個完善的監控系統和日誌系統對於一個系統的重要性不必多說。總之,只有實時了解各系統的狀態,才能保證各系統的穩定。

如何打造一個小而精的電商網站架構
如上圖所示,監控平台監控的范圍很廣,從伺服器性能及資源,到應用系統的監控。每個公司都有特定的平台統一監控的需求及解決方案,但監控平台的任務和作用基本是一致的。

1日誌

日誌是監視程序運行的一種重要的方式,主要有兩個目的:1.bug的及時發現和定位;2.顯示程序運行狀態。

正確詳細的日誌記錄能夠快速的定位問題。同樣,通過查看日誌,可以看出程序正在做什麼,是不是按預期的設計在執行,所以記錄下程序的運行狀態是必要的。這里將日誌分為兩種:1.異常日誌;2.運行日誌。

我們主要是使用log4net,將各個系統的日誌,持久化記錄到資料庫或者文件中,以方便後續的系統異常監控和性能分析。如何集成log4net,這里不多說。

日誌記錄的幾個原則:

日誌級別一定要區分清楚,哪些屬於error、warning、info等。
記錄錯誤的位置。如果是分層系統,一定要在某個層統一處理,例如我們的MVC架構,都是在各個Action中Catch異常並處理,而業務層和資料庫層這些地方的異常,都是Catch到異常後,往上一層拋。
日誌信息清晰准確有意義,日誌盡量詳細點,以方便處理。應該記錄相關系統、模塊、時間、操作人、堆棧信息等。方便後續處理。

4. 電商網站商品列表頁用的是搜索引擎還是資料庫+緩存的方式

大的電商網站頁面一般都是從緩存裡面讀取過來的,頁面更新快的緩存時間比較短。
搜索頁面建議是不加緩存,或者緩存時間極短。因為用戶關鍵詞很難確定,或許高頻詞會緩存一些,這些就得看網站的部署策略了,緩存策略只是解決了資料庫訪問的壓力
除了頁面緩存之外,資料庫還需要定時更新索引,索引的更新才是決定頁面最終命中效果的關鍵,大的電商網站索引創建會很耗時,所以需要相對較長的時間才會更新一下索引系統

5. java 電商緩存用什麼好,在線等

需要持久化就redis,否則mem,單進程guava cache,

6. 一個五年架構師為什麼基本年薪酬可以達到50萬

架構師,我想很多人都知道,其實該職位頭銜在最早的IT領域是沒有的,它是近些年來由互聯網的發展所引發的需求,因為現階段的數據量及高並發的活躍好動,引起了不少傳統的技術人員的力不從心,企業愈發關注到了系統架構的重要性,所以不同行業開始招募架構技術人員,架構師就誕生了。

架構設計的條件

以下三個條件不適合做架構設計

對架構不感興趣,但又迫於需求;

入IT行業,年限小於4年的;

主觀能動性弱,又安於現狀的;

架構設計的優勢

更好的梳理業務的結構體系;

更好的拓展、維護及性能優化;

更好的適應企業業務靈活的推進;

更好的適應大數據的沖洗和應對;

更好的穩定性、低成本及快速迭代;

架構設計時候需要注意的地方

架構設計需要注意的地方,不是怎麼把架構搭建起來,而是必須根據業務需求,嚴格分析,實現該需求需要什麼技術會更好及更長遠發展的考慮;

另外,構建好的架構雖然可以運行,但是性能需要跟起來,否則架構設計會適得其反,增加不必要的工作量,那麼下面就詳細介紹下架構設計的策略。

平台的需求

客戶需求

在線購物、在線支付或貨到付款;

購買商品後,客戶可以與客服溝通;

購買商品過程,物流的管理及跟蹤;

收取到商品後,商品、物流評價打分;

客戶的需求為最高,也代表了企業的核心需求,當然,企業需求還包括其它很多非功能性需求,具體請查看需求梳理部分。

平台的業務架構

根據業務的需求進行子系統模塊劃分,可以劃分為商品子系統、購物子系統、支付子系統、物流子系統、客服子系統、評論子系統;而非核心需求可拆分出客服子系統、評論子系統及介面子系統。另外,根據各個子系統的核心等級,可拆分出核心子系統和非核心子系統,前者包括商品子系統、購物子系統、支付子系統及物流子系統;後者,則包括評論子系統、客服子系統及介面子系統。需要注意的是一般大型電商平台的物流系統是單獨分離出來的系統(入庫、出庫、庫存管理、配送管理及貨品管理),而這里劃分為子系統的主要目的是為演示核心架構,本架構中物流子系統一般作為對接和管理獨立子系統的對接模塊哦。

1、業務拆分目的

為了解決各個模塊子系統間的耦合、維護及拓展性;

方便單獨部署子系統,避免集中部署導致一個出問題,全部不能用;

分配專門的團隊,負責具體的子系統,最大化工作效率安排;

應對大數據,高壓力時,保護核心子系統正常使用;

2、業務的架構圖

在上面的業務架構圖中,將核心和非核心業務進行拆分,同時每個系統都要獨立部署實現,做到大數據量壓下,各個系統獨立運作,提高可用性,必要時可以暫停掉非核心系統的資源開銷,保證核心業務正常為用戶服務。

平台的技術架構

在上面業務架構圖基礎上,我們需要一個技術架構的演變過程,一切只為滿足用戶的體驗和支撐為前提,所以技術架構的搭建不是一蹴而就的,而是隨著業務的不斷衍變,系統的架構會逐漸完善更新,以實現應對業務數據量的沖擊。

1、基本的架構設計

記得很早的時候,很多中小企業所採用的架構設計十分簡單,基本使用一台伺服器來滿足一切需求部署,比如:一台伺服器同時用作應用部署、資料庫存儲以及圖片存儲等,不料的是待用戶數據達到50萬以上,系統出現很多性能問題,盡管對資料庫和程序做個各種性能優化,結果仍無明顯改善,架構如下:

後來,IT程序猿發現圖片的讀寫嚴重影響了系統性能,並將圖片單獨存放在獨立伺服器中,並且在架構中引入了Cache中間件,比如:Memcache,這種做法是可取的,而且比原來性能提高了1-2個性能級別,架構設計如下:

2、初級的架構設計

前幾年,一般的電商網站的做法是選用三台伺服器,一台部署應用,一台部署資料庫,一台部署NFS文件系統,做到將各個規模龐大並耗用性能的部分剝離到不同伺服器設備,再配備必要的緩存中間件,基本可以滿足近1000萬的數據量,具體的架構圖如下:

但是,目前主流使用的網站架構已經不同,大多採用集群的方式來實現負載均衡和高可用性,架構可以是下面的樣子:

注意:

如果涉及到多台網站伺服器的話,就會存在Session如何同步的問題,一般也是最為常用的做法,就是使用Cache中間件來存儲和管理Session信息。

3、優化的架構設計

這里為解決高並發,高可用的大型電商網站的架構設計方案,主要採用了分布式、集群、負載均衡、反向代理、消息隊列及多級緩存技術。該架構設計方案,是現今比較流程的大型電商網站採用的架構模式,比如:淘寶、京東等,也許會有細微不同的地方,但大同小異哦!具體的架構圖方案如下:

平台架構的總結

這里主要總結的是優化架構,架構按層次結構羅列組織,共分為四層,層次分工明確,高拓展,低耦合,負載均衡、集群、分布式及緩存等技術的使用,架構如下:

好了,電商平台的架構設計就介紹到這里,本篇主要是介紹架構設計的思路及應用的核心技術,供在架構設計的同學參考借鑒哦!有想了解更多的可以關注我

7. php在實際電商項目開發中 一般哪些邏輯可以寫緩存

不需要及時更新的都可以緩存

8. 移動雲雲資料庫Redis有什麼產品功能緩存應用怎麼樣

首先雲資料庫Redis是一款內存型資料庫,雲資料庫Redis應用場景還挺多的,可用於游戲緩存、互聯網緩存、電商高並發,所以緩存應用是redis最為普遍的用途,各行各業都適用!

9. redis緩存商品分類,什麼時候緩存合適

寫在那裡都可以,個人感覺最好還是寫在業務層,用的時候直接取redis數據,沒有值得話查詢資料庫,然後重新add redis數據。但是在更新資料庫數據的時候,記得同步更新redis數據。

熱點內容
javatoolsfor 發布:2024-03-29 18:17:55 瀏覽:899
linuxi2c驅動 發布:2024-03-29 18:09:56 瀏覽:671
junit源碼下載 發布:2024-03-29 18:00:10 瀏覽:525
本田雅閣壓縮機不工作 發布:2024-03-29 17:59:13 瀏覽:600
溯源碼可以偽造嗎 發布:2024-03-29 17:54:45 瀏覽:56
北京編程傳 發布:2024-03-29 17:54:44 瀏覽:435
編程畫曲線 發布:2024-03-29 17:48:59 瀏覽:59
簡單存儲服務s3 發布:2024-03-29 17:48:46 瀏覽:336
安卓手機的usb功能在哪裡設置 發布:2024-03-29 17:46:27 瀏覽:758
配置文件ini如何寫 發布:2024-03-29 17:31:05 瀏覽:997