久草视频2-久草视-久草社区视频-久草色在线-久草色视频-久草软件

換個思路看12306,其核心模型設計思路到底復雜在哪里?

36氪  ?  掃碼分享
我是創始人李巖:很抱歉!給自己產品做個廣告,點擊進來看看。  
不就是一個訂票網站嗎,12306 的核心模型設計思路究竟復雜在哪里?

編者按:本文作者湯雪華,網名 netfocus,2006年 畢業于浙江大學,目前住在杭州。對 DDD,以及 CQRS 架構比較感興趣。目前一直致力于開發和完善 ENode、EQueue。文章首發于微信公眾號InfoQ(ID:infoqchina),授權 36 氪轉載。

元宵節結束,年就真的過完了。揮別故里,回到打拼的城市,理性思維是否也跟著工作狀態一起回歸了呢?每一年的春運都是對 12306 的一次大考,拋去盲從和偏見,讓我們用工程師的思維重新打量、從業務分析的角度去探討,12306 的核心模型設計思路和架構設計到底復雜在哪里?

為什么我要研究這個問題?

春節期間,無意中看到一篇文章,文章中講到 12306 的業務復雜度遠遠比淘寶天貓這種電商網站要復雜。后來自己想想,也確實如此。所以,很想挑戰一下 12306 這個系統的核心領域模型的設計。一般的電商網站,購買都是基于商品的概念,每個商品有一定量的庫存,用戶的購買行為是針對商品的。當用戶發起購買行為時,系統只需要生成訂單并對用戶要購買的商品減庫存即可。但是,12306 就不是那么簡單了,具體復雜在哪里,我下面會進一步分析。

另外一個讓我寫這篇文章的原因,是我發現也許是否是因為目前 12306 的核心領域模型設計的不夠好,導致用戶購票時要處理的業務邏輯異常復雜,維護數據一致性的難度也幾百倍的上升,同時面對高并發的訂票也難以支持很高的 TPS。我覺得,越是復雜的業務,就越要重視業務分析,重視領域模型的抽象和設計。如果不假思索,憑以往經驗行事,則很可能會被以往的設計經驗先入為主,陷入死胡同。

技術人員往往更注重技術層面的解決方案,比如一上來就分析如何集群、如何負載均衡、如何排隊、如何分庫分表、如何用鎖,如何用緩存等技術問題,而忽略了最根本的業務層面的思考,如分析業務、領域建模。我認為越是復雜的業務系統,則越要設計一個健壯的領域模型。如果一個系統的架構我們設計錯了,還有補救的余地,因為架構最終沉淀的只是代碼,調整架構即可(一個系統的架構本身就是不斷演進的);而如果領域模型設計錯了,那要補救的代價是非常大的,因為領域模型沉淀的是數據結構及其對應的大量數據,對任何一個大型系統,要改核心領域模型都是成本非常高的。

本文的重點不是在如何解決高并發的問題,而是希望從業務角度去分析,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 種:

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

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

  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、聚合設計

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

  1. 車次名稱,如 G71;

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

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

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

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

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

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

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

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

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

3、如何為票分配座位?

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

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

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

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

假設現在的情況是座位有 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、模型分析總結

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

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

  • 判斷是否可出票;

  • 選擇可用的座位;

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

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

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

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

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

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 的設計思路:

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

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

總結

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

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

原創文章,作者:Retric,如若轉載,請注明出處:http://36kr.com/p/5043608.html

“看完這篇還不夠?如果你也在創業,并且希望自己的項目被報道,請 戳這里 告訴我們!”

本文被轉載2次

首發媒體 36氪 | 轉發媒體

隨意打賞

提交建議
微信掃一掃,分享給好友吧。
主站蜘蛛池模板: 欧美成人极品 | 色激情网 | 亚洲精品一区二区另类图片 | 日本专区在线 | 国产精品久久一区二区三区动漫 | 国产精品186在线观看在线播放 | 人人妻人人澡人人爽人人精品浪潮 | 久久欧| 欧美日一本 | 久久丁香五月天综合网 | 无码少妇精品一区二区免费动态 | 国产对白受不了了中文对白 | 久久99精品久久久水蜜桃 | 女人18毛片水最多 | 成年人黄色 | 久久久久久伊人高潮影院 | 奶涨边摸边做爰爽别停快点视频 | 日本乱偷互换人妻中文字幕 | 久久久久久欧美精品色一二三四 | 成人在线精品视频 | 99久久久久久国产精品 | 久久99精品一区二区蜜桃臀 | 国产精品99精品无码视亚 | 精品日韩久久 | 大胸美女拍拍18在线观看 | 天天在线综合 | 亚洲天堂bt | 一级黄毛片 | 国产做无码视频在线观看浪潮 | 国产欧美一区二区三区在线 | yy111111少妇无码影院 | 欧美三级韩国三级少妇99 | 亚洲国产精品成人综合久久久久久久 | 日本涩涩网 | 国产毛片乡下农村妇女bd | 日韩黄色片免费看 | 日韩精品在线视频免费观看 | 99久久婷婷国产综合精品青牛牛 | 久久这里只有精品18 | 国产精品青草综合久久久久99 | 99久久精品午夜一区二区 | 色悠悠网 | 亚洲成人影音 | 日韩在线三区 | 亚洲无人区码一码二码三码的含义 | 久久精品黄aa片一区二区三区 | 一级大毛片 | 99久久精品国产片果冻的功能特点 | 亚洲中文字幕精品久久 | 不卡av在线免费观看 | 国产精品2区 | 久久精品6 | 国产av无码专区亚洲a∨毛片 | 羞羞麻豆国产精品1区2区3区 | 欧美激情一区二区在线观看 | 亚洲福利网站 | 少妇乱子伦在线播放 | 久久aaaa片一区二区 | 午夜小视频免费观看 | 欧洲妇女成人淫片aaa视频 | 天堂一区二区mv在线观看 | 男人激烈吮乳吃奶视频 | 国产九一视频在线观看 | 日韩中文字幕亚洲欧美 | 亚洲视频123| 国产黑丝91 | 一本大道久久a久久综合婷婷 | 中文 在线 日韩 亚洲 欧美 | 中文文字幕文字幕亚洲色 | 哪里可以看毛片 | 性生交大片免费看 | 成年人网站黄 | 国产精品伦理久久久久 | 涩涩网站免费 | 久久久久久av无码免费网站下载 | 欧洲熟妇色xxxx欧美老妇软件 | 日日摸日日碰夜夜爽av | 欧美视频免费看欧美视频 | 粉嫩91精品久久久久久久99蜜桃 | 欧美精品一区二区视频 | 国产精品免费视频一区二区 | 一区二区三区四区在线视频 | 国产乱子伦农村xxxx | 精品一区二区亚洲 | 超碰在线人人 | 九九热免费观看 | 久久久一本 | 午夜影院0606| 亚洲一区二区三区偷拍女厕 | 在线观看岛国av | 国产精品一卡二卡三卡 | 欧美日韩在线视频播放 | 中文字幕在线国产 | 久热超碰 | 日本一区午夜艳熟免费 | 国产成人精品久久二区二区91 | 天天操夜夜操夜夜操 | 国产手机在线精品 | 色综合久久综合网 | 国产高清不卡免费视频 | 午夜时刻免费入口 | 国产自在自拍 | 性夜久久一区国产9人妻 | 成人午夜影院 | 日本人体一区 | 国产麻豆剧传媒精品国产av | 97久久精品人人澡人人爽古装 | 国产精品免费一区 | 日本三级久久 | 亚洲精品一区二区三区h | 日韩欧美手机在线 | 精品国产乱码久久久久久三级人 | 西野翔之公侵犯中文字幕 | 在线国产三级 | 午夜视频在线观看吗 | heyzo亚洲| 中文字幕熟妇人妻在线视频 | 看免费毛片 | 国产综合视频一区二区三区 | 欧美又大粗又爽又黄大片视频 | 中文字幕在线天堂 | 欧美寡妇性猛交ⅹxxx | 国产69av | 三级黄色免费片 | 亚洲人成无码网站在线观看 | 日本aaaaa女人裸体h片 | 久久综合久久综合九色 | 一本色道久久hezyo加勒比 | 精品国产污污免费网站 | 色诱视频在线观看 | 99vv1com这只有精品 | 免费精品视频一区二区三区 | 国内精品人妻无码久久久影院蜜桃 | 黑人ⅴvideo暴力亚洲娇小 | 91视频国产精品 | 中文字幕亚洲色图 | 亚洲人成网站在线播放942 | 国产精品福利在线 | 毛茸茸绝色孕妇孕交 | yy6080亚洲精品一区 | 久久99国产精品久久99果冻传媒新版本 | 亚洲国产天堂一区二区三区 | 亚洲剧情av| 99色在线观看 | 欧美激情一区二区 | 亚洲免费精品视频 | 偷窥自拍欧美色图 | 污网站在线播放 | 国产理论视频在线观看 | 久久伊人爱 | 日产91精品卡2卡三卡四 | 久草视频手机在线观看 | 亚洲伊人伊色伊影伊综合网 | 国产传媒毛片精品视频第一次 | 免费国产区 | 五月天堂婷婷 | 国模大尺度自拍 | 久青草免费视频 | 插b内射18免费视频 亚洲欧美另类激情综合区 很黄很色60分钟在线观看 | 饥渴的熟妇张开腿呻吟视频 | 国产精品久久久久久久久久 | 亚洲欧洲成人av每日更新 | 91亚洲国产成人精品性色 | 天干天干天啪啪夜爽爽av软件 | 乱淫的女高中暑假调教h | 久久思| 国产精品国产三级国产aⅴ中文 | 欧美在线免费视频 | 在线免费观看视频你懂的 | 欧美三级韩国三级日本三斤在线观看 | av地址在线 | 在线免费精品视频 | 国产精品aⅴ | 日本少妇翘臀后式gif动态图 | 暴力强奷在线播放无码 | 免费网站看v片在线观看 | 亚洲欧美成人一区二区三区 | 色99色| 91蜜桃臀久久一区二区 | 国产成人久久精品77777的功能 | 裸体精品bbbbbbbbb | 国产三级av在线播放 | 欧美日韩亚洲在线观看 | 嫩草影院wwwnyz五月天 | 国产毛片一区二区精品 | 天天射日日 | 久久97久久97精品免视看秋霞 | 麻豆毛片| 国产日产欧美一区二区 | 亚洲国产婷婷香蕉久久久久久99 | 欧洲一区二区三区四区 | 国产精品久久久久久久久久久久久久 | 国偷自产av一区二区三区小尤奈 | 久久久国产精华特点 | 日韩一本之道一区中文字幕 | 九九热在线免费观看 | 拔萝卜在线 | 国产精品丝袜久久久久久不卡 | 国产麻豆a毛片 | 中文字幕日产乱码中 | 亚洲综合另类小说色区一 | www婷婷com| 岛国精品在线 | 国产黄色一区二区 | 69综合| 夜夜天天干 | 人妻夜夜添夜夜无码av | 中文字幕精品一区二区精品 | 男人边吃奶边揉好爽免费视频 | 国产偷v国产偷∨精品视频 国产偷v国产偷v精品视频 | 日韩激情网站 | 国语啪啪 | 日本亲子乱子伦xxxx | 毛片在线免费观看网址 | 开心激情久久 | 9l视频自拍九色9l视频大全 | a级免费黄色片 | 91夜色视频| 午夜寂寞影视 | 午夜性刺激免费看视频 | www.av在线.com| 91九色丨porny丨丰满6 | 夜夜嗨av一区二区三区四季av | 日日摸夜夜添夜夜添国产2020 | 精品人妻久久久久久888 | 亚洲狠狠爱一区二区三区 | 亚洲久久视频 | 免费人成在线观看视频播放 | 99爱爱| 国产做a爱片久久毛片a片高清 | 日本伦理中文字幕 | 亚洲国产精品久久久 | 青青草免费观看视频 | 欧美精品入口 | 男女裸交免费无遮挡全过程 | 欧美极品在线视频 | 99成人在线视频 | 91精品国产福利一区二区三区 | 成人a视频 | 欧美性猛交xxxx黑人交 | 高潮添下面视频免费看 | 中国黄色录像一级片 | 日韩在线视频观看 | 精品国产大片大片大片 | 日韩精品一区二区在线 | 日韩伦理一区二区 | 免费看av大片 | √新版天堂资源在线资源 | 黄网站在线观看视频 | 日韩欧美在线综合网 | 日韩经典中文字幕 | 久久久成人av | 久久精品国产成人av | 国产乱子夫妻xx黑人xyx真爽 | 欧美日韩另类视频 | 一色桃子av大全在线播放 | 国产精品视频免费看人鲁 | 欧美黑人猛交 | 国产精品嫩草55av | 国产一级久久久 | 激情麻豆| 黄色录像大片 | 成人伊人精品色xxxx视频 | 天天激情站 | 汤唯的三级av在线播放 | 九九热99久久久国产盗摄 | 亚洲精品乱码久久 | 免费的av在线 | 天堂伊人久久 | 精品国产乱码久久久久夜深人妻 | 农村真人裸体丰满少妇毛片 | 欧美日韩免费 | 免费国产玉足脚交视频 | 国产麻豆91精品三级站 | 国产精品对白久久久久粗 | 国产探花在线精品一区二区 | 无码一区二区三区免费 | www男人的天堂com | 久久久无码中文字幕久... | 毛片在线免费观看网址 | 欧美美女爱爱视频 | 一级国产航空美女毛片内谢 | 久久网一区 | 成年在线观看免费视频 | 伊人精品久久久大香线蕉 | 777奇米888色狠狠俺也去 | 性欧美1819性猛交 | 国产精品久久久久久久久夜色 | 久久狼人天堂 | 日韩av男人的天堂 | 国产成人a在线观看网站站 又大又粗又爽免费视频a片 | 玩丰满高大邻居人妻无码 | 黄色片高清| 亚洲狠狠丁香综合一区 | 麻豆传媒一区二区 | 噜噜噜噜狠狠狠7777视频 | 伊人久久大香线蕉亚洲五月天 | 亚洲男女一区二区三区 | 少妇肥臀大白屁股高清 | 9·1·黄·色·视·频 | 3d动漫啪啪精品一区二区中文字幕 | 欧美最猛性xxxⅹ丝袜 | 免费簧片在线观看 | 免费a级黄毛片 | 消息称老熟妇乱视频一区二区 | 国产香蕉精品视频 | 亚欧激情乱码久久久久久久久 | 一级做a爰全过程免费视频毛片 | 欧美亚洲精品在线观看 | 欧美一区二区 | 中文字幕23页| av黄色在线观看 | 国产精品久久久久影院 | 日日操夜夜骑 | 四影虎影免费在线观看 | 理论片第一页 | 国产精品无码av不卡顿 | 欧美午夜精品一区二区蜜桃 | 99久久伊人 | 午夜爱爱网站 | 欧美一区二区三区激情 | 国产成人天天5g影院在线观看 | 欧美一区二区日韩国产 | 神马影院午夜伦理 | 国产精品黄在线观看免费软件 | 中文字幕人成无码人妻综合社区 | 超清 忍不住的亲子伦中文字幕 | 久久精品噜噜噜成人av农村 | 亚洲免费观看视频 | 久9re热视频这里只有精品 | 国产欧美日韩另类在线专区 | 国产精品麻豆入口 | 亚洲精品v日韩精品 | 玖草视频在线观看 | 内射爽无广熟女亚洲 | 久久老司机 | 国产高清久久 | 精品国产精品一区二区夜夜嗨 | 国产成人高清在线 | 日本牲交大片无遮挡 | av大全在线观看 | 五月婷婷欧美 | 欧美精品色哟哟 | 一区二区在线精品 | 日本乱偷互换人妻中文字幕 | 手机在线看片福利 | 99综合色| 激情小说激情视频 | 国产一级特黄aa大片出来精子 | 毛片网特黄 | 久久强奷乱码老熟女网站 | 在线播放国产视频 | 乳罩脱了喂男人吃奶视频 | 国产乱对白精彩 | 伊人干综合 | 91视频在线观看视频 | 日韩欧美国产精品 | 一级美女黄色片 | 一区二区三区国产亚洲网站 | 超乳在线| h 吃奶 呻吟 调教h | 欧美性淫爽ww久久久久无 | 国产成人福利 | 亚洲国产欧洲 | 鸭子tv国产在线永久播放 | 91福利在线免费观看 | 欧美综合网 | 国产精品久久伊人 | 亚洲精品精华液一区 | 91视频最新地址 | 国产免费一区二区三区四区五区 | 国产乱肥老妇国产一区二 | 久久免费视频观看 | 国产精品久久久av久久久 | 亚洲一区二区a | 国产无限制自拍 | 熟睡人妻被讨厌的公侵犯 | 99久久精品久久久久久动态片 | 黄a无码片内射无码视频 | 大又大又粗又硬又爽少妇毛片 | 婷婷久久香蕉五月综合加勒比 | 久久亚洲精品成人无码网站蜜桃 | 国产91热爆ts人妖在线 | 亚洲中文字幕无码爆乳av | 亚洲免费综合色在线视频 | 国产一区第一页 | 国产成人免费高潮激情视频 | 特级做a爰片毛片免费看无码 | 黑人巨大精品欧美一区二区桃花岛 | 日本少妇被黑人xxxxx | 欧美巨大另类极品videosbest | 嫩草视频在线观看 | 黄色性情网站 | 日本一级待黄大片 | 国产另类精品 | 羞羞啪啪调教play男男黄 | 欧美福利第一页 | 久久999精品久久久有什么优势 | 国模小黎自慰gogo人体 | 欧美性做爰免费观看 | 欧美老肥妇做.爰bbww视频 | 久久99精品久久久久久久久久久久 | 饥渴少妇勾引水电工av | 四虎国产精品成人永久免费影视 | 国产精品视频免费在线观看 | 日本精品不卡 | 欧美成人图区 | 香蕉av777xxx色综合一区 | 无码人妻精品一区二区蜜桃色欲 | 日本裸体精油4按摩做爰 | 午夜影院免费在线观看 | 欧美激情精品久久久久久 | 在线无码va中文字幕无码 | 人人爽人人爽人人片av亚洲 | 精东粉嫩av免费一区二区三区 | 少妇之白洁番外篇 | 国产黄色片视频 | 国产成人午夜高潮毛片男男爱 | 色偷偷888欧美精品久久久 | 老子影院午夜伦手机不四虎卡 | 午夜国产片 | 亚洲视频黄色 | 成在线人免费无码高潮喷水 | 性欧美激情 | 色香蕉网站 | 午夜a区 | 亚洲精品成人av在线 | 91超碰中文字幕久久精品 | 99噜噜噜在线播放 | 捆绑紧缚一区二区三区在线观看 | 九色综合狠狠综合久久 | 亚洲砖区区免费 | 亚洲日韩日本中文在线 | 亚洲精品久久酒店 | 日韩中文字幕一区二区 | 日韩视频在线观看一区二区 | 九九在线精品 | 亚洲特级黄色片 | 一本久久a久久精品亚洲 | 少妇又色又紧又爽又高潮 | 日韩精品中字 | 国产精品爽爽久久久久久豆腐 | 激情网五月| 丰满少妇高潮惨叫正在播放 | 天天透天天操 | 日韩中文字幕免费观看 | 痞帅大猛xnxx精品打桩 | 成全世界免费高清观看 | www久久久天天com | 亚洲色大成网站www永久在线观看 | 51国产在线 | 国产一区二区三区四区五区密私 | 国产乱码日产乱码精品精 | 999福利视频| 亚洲一区在线观看视频 | 日韩高清不卡在线 | 全免费又大粗又黄又爽少妇片 | 全黄性性激高免费视频 | 亚洲精品suv精品一区二区 | 黄a网站| 英语老师丝袜娇喘好爽视频 | 自拍偷拍亚洲综合 | 少妇啊灬啊别停灬用力啊房东 | 91精品久久久久久久91蜜桃 | 中文无码人妻有码人妻中文字幕 | 91亚洲精品久久久蜜桃借种 | 特污兔网站免费观看 | 日韩影视在线 | 美女的屁股眼网站 | 国产在线小视频 | 天天躁日日躁狠狠躁av麻豆男男 | 亚洲精品午夜视频 | 国产韩国精品一区二区三区久久 | 一乃葵在线| 国产激情视频在线观看 | 亚洲丁香五月天缴情综合 | 日韩v片| 99re6在线视频精品免费 | xxx在线播放xxx | 亚洲精品久久久狠狠爱小说 | 中文字幕一级二级三级 | 永久黄网站色视频免费直播 | 粉嫩av一区二区三区四区在线观看 | 播放毛片 | 晨勃顶到尿h1v1 | 波多野结衣中文字幕一区二区三区 | 亚洲免费精品网站 | 狠狠色噜噜狠狠狠狠7777米奇 | 先锋久久 | 色婷婷精品久久二区二区蜜臂av | 亚洲国产精品激情综合图片 | 欧美成人精品第一区 | 成人区人妻精品一熟女 | 无码专区—va亚洲v天堂麻豆 | 国产精品swag | 人妻精油按摩bd高清中文字幕 | 手机av在线免费 | 91精品国产色综合久久不卡98 | 成人无码网www在线观看 | 人人妻人人澡人人爽国产一区 | 亚洲国产精品久久久久久久 | 国产成人精品福利 | 一级做性色a爱片久久毛片欧 | 国产乱淫av | 夜夜夜高潮夜夜爽夜夜爰爰 | 黄色精品一区二区 | 欧美性猛交99久久久久99按摩 | 无码专区一ⅴa亚洲v天堂 | 中文字幕av一区二区三区高 | 无码137片内射在线影院 | 日日爱影视 | 欧美特级黄色录像 | 同性做爰猛烈全过程 | 久久人人爽人人爽人人片亞洲 | 国模一区二区三区白浆 | 国产亚洲成人av | 国产欧美二区 | 日韩国产在线一区 | 午夜影皖精品av在线播放 | 成人动漫h在线观看 | 无码精品尤物一区二区三区 | 色综合天 | 国产精品后入内射日本在线观看 | 久久的久久爽亚洲精品aⅴ 久久第一页 | 久久久精品999 | 国产猛男猛女超爽免费视频 | 我要看黄色a级片 | 99香蕉国产精品偷在线观看 | 久久99精品国产麻豆91樱花 | 日本少妇xlxxx| 狠狠色婷婷久久综合频道日韩 | 影音先锋在线资源无码 | 国产亚洲人成a在线v网站 | 四虎影院黄色 | 老头吃奶性行交 | 成人免费毛片免费 | 无码中文字幕日韩专区 | 国产啪精品视频网站 | 一区二区精品在线观看 | 国产精品国产三级国产有见不卡 | 日韩免费久久 | 免费观看黄色网址 | 999精彩视频| 亚洲国产欧美日韩 | 首页 亚洲 欧美 制服 丝腿 | 国产蜜臀av在线一区尤物 | 欧美亚洲在线视频 | 国产94在线 | 亚洲 | 特级西西人体444www高清大胆 | 亚洲精品乱码久久久久久日本 | 精品国产91久久久久久久 | 欧美精品一区二区精品久久 | 成人羞羞视频在线观看免费 | 男人的网址 | 免费人成激情视频在线观看冫 | av资源网在线 | 噜噜噜久久 | 影音先锋成人资源网 | 国产精品激情av久久久青桔 | 中文国产一区 | 久久99操 | 无码人妻一区二区三区免费 | 狠狠爱俺也去去就色 | 黄色网战入口 | 无码137片内射在线影院 | 日本aⅴ写真网站 | 佐佐木明希99精品久久 | 欧美一级特黄aa大片 | 97视频在线观看播放 | 亚洲精品一区二区三区不 | www.jizz国产| 国产免费又色又爽粗视频 | 用力挺进新婚白嫩少妇 | 日本黄页网站免费观看 | 粉嫩av一区二区在线播放免费 | 国产二级一片内射视频播放 | 色综合五月 | fc2成人免费人成在线观看播放 | 男人j进入女人j内部免费网站 | 国产黄色片网站 | 久久久久久久久国产精品 | 久久亚洲高潮流白浆av软件 | 四虎成人精品永久免费av九九 | 中文字幕+乱码+中文字幕无忧 | 超碰人人超碰人人 | 成人在线观看av | 久久久国产乱子伦精品作者 | 欧美精品一区在线观看 | 一道本在线观看视频 | 免费黄色短片 | 成人天堂网 | 日本精品视频一区 | 亚洲xxx视频 | 亚洲精品无码午夜福利中文字幕 | 久久国产劲暴∨内射新川 | 欧美 日韩 国产 亚洲 色 | 无码毛片视频一区二区本码 | 日本三级中国三级99人妇网站 | 蜜臀久久99精品久久久久宅男 | 精品一区二区三区四区五区六区 | 日本无遮挡大尺度床戏网站 | 色老妹 | 久久99热久久99精品 | 爽好多水快深点欧美视频 | 国产乱淫av片免费 | 中文字幕在线观看免费 | 中日韩中文字幕 | 亚洲作爱网 | 精品国产一区二区三区粉芽 | 亚洲色图网友自拍 | 日韩视频精品在线 | 男女草逼网站 | 国产 欧美 视频一区二区三区 | 天天躁日日躁狠狠躁性色av王爷 | 色综合久久五月 |