問題: 1.購物車中的數據是否應該存儲在數據庫中? 我特別想知道在真正的項目中,那些真正的軟件工程師是如何考慮這個問題的。在Google上一搜,搜到了一篇咱園子裡一位網友的觀點:購物車應該是個臨時存儲數據的模塊,他將其存放在Session對象中。這位網友說的很有道理,不過我並不喜歡這樣的做法。如果大家都將其存儲在Session對象中,成千上萬個用戶一同購物的話,想必ASP.NET服務器必將承受巨大的負載。也許像我們國內的網站可能會好一些,但想Amazon這樣的網站,怎麼做的呢?Amazon中國網站,也就是Joyo的網站,並不是將其存儲在Session對象中,因為我如果這次放入購物車中的商品沒有提交訂單,下次登錄後購物車中還會有這些商品。因此,我想他們可能是將這些購物車中的數據放入了數據庫中。
回復: 把購物車存放在Session中,這種做法似乎只存在於大學裡的課程設計或者一些無人在意的實習項目中出現。事實上,基本所有的電子商務網站都把購物車數據存放到了數據庫裡。下面是一些解釋和設計上需要注意的地方:
1、Session並不適合做大數據量的數據存放,當用戶比較多的時候勢必影響服務器性能,這是應該避免的。
2、Session存在意外丟失的問題,或者當用戶不小心關閉浏覽器,都會引起購物車內物品全部丟失,用戶體驗很不好
3、Cookies可以解決上面一條裡Session的問題,但是Cookies的長度限制,以及使用Cookies時的通訊開銷,還有安全性方面考慮,Cookies並不適合做購物車
4、比較好的用戶體驗是,無論用戶登錄與否,都可以在一定時間內記錄購物車狀態,這就要求數據庫內購物車不能與用戶捆綁太死
5、放到購物車裡的商品,一般都是有購買意向的商品,但並不一定會成為真實的訂單,這時候,保留這份數據,對數據挖掘、業務分析有至關重要的作用
問題: 2.關於並發?
原來我在開發自己的模擬網站的時候,曾經想到這樣一個問題:如果一個客戶在網站將一些圖書放入了購物車,那麼這些數量的圖書是否應該從庫存中減去呢?當時我是這樣做了。我將購物車中相應圖書的數量從數據庫中減去,以防止此時其他用戶看到”虛”的庫存數量(如果沒有減去,那麼其他用戶是可以購買的。例如:庫存中圖書的數量是10本,客戶A將10本放入自己的購物車,此時客戶B也將10本放入自己的購物車,那麼誰將購買到此書將成為一個矛盾)。不過我這樣做的結果是,每當客戶更新購物車的同時就會同數據庫有一次交流,加大了數據服務器的負擔。Amazon.cn在這方面做的也不是很好,前些日子相信大家可能都遇到了當購買《深入理解操作系統》一書的時候,本來生成了訂單,但是卻在第二天告知缺貨的事情。這一事件確實非常影響Amazon.cn的信譽,不知道現在他們的系統是否已經解決這一問題,不過現在《深入理解操作系統》一書的Joyo價已經今非昔比了。不知道各位高手是如何解決這一問題的,歡迎大家將自己的成功經驗寫在評論中。
回復: 首先說一下數據庫服務器的負擔,想一下每訪問一個頁面要對數據庫進行多少次訪問,然後想一下多次訪問才能換來一次放購物車的操作(訪問次數主要取決於網站易用性的設計,這是另外一個話題),所以,雖然在這裡修改設計可以減輕一些數據庫壓力,但是這裡並不是瓶頸,丁學認為不需要在這裡太在意。
目前比較通用的做法,購物車的商品是不會立即扣減庫存的,主要是為了防止有人通過購物車惡意占用商品,另外一般都會給一個冗余量,因為大部分購物車裡的商品不會進入最終的成功訂單,不可以讓購物車影響銷量,這是必須做到的。庫存一般在訂單成功提交的時候扣減庫存,也就是用戶在提交訂單時,你還有一次機會提示用戶沒有庫存了,所以更沒有必須在放到購物車時就扣減庫存。對於“成功訂單”,並不是所有用戶提交的訂單都算成功訂單,這裡有一個自動審單的過程,這個程序不好寫,但確實很重要,根據以前的數據分析、用戶行為、用戶信譽等經驗性的數據來由系統在幾分鐘內自動對訂單完成一次審核,審核力度與行業有關,這樣可以杜絕大部分的假訂單,其中一部分可能還要由自動審單系統轉交人工審核。
這裡有一個特殊情況,有一些特殊商品比如演唱會門票,可能會存在在線選座的行為,這種時候放購物車後留座變得比較有用,現在的做法一般是放購物車後立即留座,但某一段時間未成為真實訂單的話就自動釋放,比如十分鐘,雖然無法完全杜絕惡意占座,不過可以解決多數問題。現在票務方面的成功訂單和大部分其他行業不太一樣,票務行業的在線選座成功訂單的判斷標准為是否已經成功支付,就是說除非你給錢了,不然只能給你留十分鐘。
問題: 3.訂單和訂單明細同購物車的關系
我想這個問題可能一直是此類網站的一個大問題吧!前兩天,CSTP的陳老師還曾在電話中面試我這道題,我當時很緊張,問題答的不是很清楚。其實這個問題簡單的想並不難:兩個表訂單和明細,訂單表中每列指向明細表中的對應列。外鍵就是訂單表中的訂單號。
回復: 這個問題比較簡單,一種是放購物車裡就當是訂單了,拿一個狀態標識一下,這種狀態下訂單是可修改的,購物車合並進訂單系統(注意處理用戶登錄與非登錄狀態);第二種是有單獨的購物車表,當最終提交訂單時,復制購物車內的信息進訂單和訂單明細表。後一種用得比較多一些,具體選擇哪個取決於行業和商品屬性。
問題: 4.明細表中訂單號的生成?
這個問題繼承第3個問題,我一直不知道應該如何解決此問題。我有兩個解決方案,一個是使用觸發器,另一個是編程。前者在客戶每次放入購物車中一種商品的同時增加一個明細,確認購買後生成訂單,將明細表中的購買狀態更改以觸發觸發器將生成一個訂單號(當然這個訂單號既可以在觸發器中編程也可以是讓訂單表訂單號的一列設置為自動生成序號)。後者將判斷訂單號,然後將其加1以生成新的訂單號。但是這兩個方案我總是覺得非常不好,很想知道在商用網站中訂單號是如何處理的。
回復: 首先我個人認為觸發器的方案不可取,理由不多說,不然又是一大坨。這裡也有兩種做法,一種是訂單表自動生成編號,生成訂單時,先寫入訂單表,然後取回訂單號再更新訂單明細表;另一種是按業務規則生成訂單號,當訂單號已知後隨便先生成訂單記錄還是明細記錄都可以,但是要保證明細記錄最終一定有訂單記錄,不然會有很多詭異的明細項。後一種辦法又有兩種做法,一是訂單號由數據庫生成,一般采用臨時表,好處是可以全業務通用流水號,另一種是訂單號由程序生成,程序生成時可以使用GUID,但更好的辦法是使用訂單時間加標識值,時間部分可以根據訂單量來確定粒度大小,標識部分采用有序編號,時間粒度還要考慮防止別人大概統計你的業務量(汗~~~這個也是另外的問題,很多做法,看情況了,改天有空再寫個有關訂單號生成的文章吧,先回復這麼多,大概信息也夠了……)