(專案隨筆)關於訂單系統的思考
訂單系統幾個特點:
1、歷史資訊多(每一條訂單完成後,生成一條歷史資訊,並且一般情況下,久遠的訂單資訊不回被經常檢視)
2、併發量高(特別是秒殺系統生成的訂單,每秒會有成百上千條訂單)
3、訂單id必須全域性唯一
一、分庫分表
隨著訂單量的增加,資料庫發展如下:
- 單一的資料庫
- 一主一從
- 雙主多從,讀寫分離
- 分表分庫,提高併發
已知Mysql單表效能超過千萬級別會嚴重下降,按照千萬級別來計算,假設訂單系統分為16個庫,每個庫64個表進行儲存,共1024個表,那麼,Mysql最高可以儲存百億級別的訂單。隨著儲存問題的解決,複雜度也會隨之增加,例如一下問題:
- 多庫多表,如何保證訂單編號唯一
- 查詢複雜度增加,怎麼解決(不知道資料具體在哪個表中)
- 買家檢視訂單在哪裡查,賣家檢視訂單在哪裡查
- 再大的儲存量,隨著資料的增長,總會遇到瓶頸,應該怎麼擴容
下面依次解決上面的問題:
1、生成全域性唯一的訂單編號
這裡採用了:機器ID+時間戳+自增序列(+userid後兩位);
這裡的機器id是因為叢集部署的時候,不同機器上的訂單系統的機器id是不一樣的,生成的訂單id也就不一樣了。
時間戳可以精確到毫秒,但是如果每毫秒任然有併發,單純使用時間戳並不能完全生成唯一訂單id
自增序列每個表自己的自增序列,保證單表的訂單id唯一
userid後兩位,給訂單id賦予一定含義。
詳情可見:分散式系統唯一ID生成方案彙總
2、查詢複雜度的降低-----mycat資料庫中介軟體
中間價可以使用阿里的mycat連線,具體使用檢視mycat文件。優點:程式碼實現簡單,跟分庫前差不多。
而直接使用jdbc連結,需要自己計算哪條訂單存入哪個庫,優點是:直接連結資料庫效能更好,缺點是程式碼複雜度高。
3、買家賣家訂單設計
由於買家與賣家有不同的查詢特性,買家(使用者)只會查詢自己的訂單,而賣家(商家)會查詢自己店鋪的訂單,還有管理者,他可以查詢所有的訂單並且統計。
訂單的查詢特性是:一般三個月之前的訂單是很少被查詢的。
所以我這裡設計了兩個訂單表,一個是針對使用者的,一個是針對商家和管理者的。
使用者訂單表UOrderId根據訂單的後兩位(也就是生成訂單id時的使用者id後兩位),進行分庫分表,這樣分得的訂單表中,同一個使用者的訂單一定是在一個表中的,使用mycat查詢的時候,減少了mycat的計算等的操作。
商家訂單表OOrderId根據訂單產生的時間進行分庫分表,我們按照一個月一個月分表,分為12個表,商家和管理者查詢這個表,由於經常檢視的表只有幾個,所以,只會查詢特定的幾個表,減少查詢的複雜度。
4、擴容問題
由於訂單系統不僅會通過訂單號查詢訂單,還有可能會通過使用者id查詢,通過商家id查詢,查詢所有訂單等,但是無論是哪種身份的使用者查詢都有一個特性,就是很少會查詢三個月之前的資料,所以我們可以考慮吧三個月之前的資料遷移到歷史資料庫中,給新的資料騰空間,從而解決容量增長的問題。
例如:我們可以在3,6,9,12月份的月底進行資料遷移,在6月底,將3月之前的資料都遷移到歷史資料庫中,歷史資料庫不要求有多高的效能,只要空間足夠就可以,節約成本。
二、使用MQ,起緩衝作用,緩解併發問題
這裡我們在生成訂單的時候,不直接呼叫生成訂單的介面,而是將訂單資訊傳送到MQ中,利用Mq佇列先進先出的特性,一個是使用MQ系統做緩衝作用,還有就是作為MQ的消費者,一定是一個一個處理訂單,所以,減少了訂單系統的壓力,也減少了併發。
三、訂單系統流程