訂單中臺-3萬+QPS高併發系統架構設計

  • 多應用實例全局唯一訂單號
  • 分庫分表&擴容問題
  • 訂單C端查詢&B端查詢&保存
  • 訂單緩存設計&3萬+qps
  • 訂單配置中心
  • 訂單狀態機
  • 訂單熔斷&降級

多應用實例全局唯一訂單號(按時間趨勢遞增,訂單id帶有業務標示)

      xx-snowflake簡介

                    

                    改造版 xx-snowflake方案採用“1+5+41+5+12”的方式組裝ID號,使用Zookeeper持久順序節點的特性自動對snowflake節點配置wokerID。 xx-snowflake是按照下面幾個步驟啓動的:

  1. 啓動Leaf-snowflake服務,連接Zookeeper,在leaf_forever父節點下/snowflake/order-center/forever/檢查自己是否已經註冊過(是否有該順序子節點)。(workerid:/snowflake/order-center/forever/192.168.17.197:2181-0000000000)
  2. 如果有註冊過直接取回自己的workerID(zk順序節點生成的int類型ID號),啓動服務。
  3. 如果沒有註冊過,就在該父節點下面創建一個持久順序節點,創建成功後取回順序號當做自己的workerID號,啓動服務。

        xx-snowflake優點       

                       (1) 基於snowflake算法訂單號趨於遞增

                     (2) 固定17位+2位業務標示。訂單業務標示佔據低2位。

                       (3) xx-snowflake對Zookeeper生成機器號做了弱依賴處理,即使Zookeeper有問題,也不會影響服務。Leaf在第一次從Zookeeper拿取workerID後,會在本機文件系統上緩存一個workerID文件。即使ZooKeeper出現問題,同時恰好機器也在重啓,也能保證服務的正常運行。這樣做到了對第三方組件的弱依賴,一定程度上提高了SLA。

                      (4) 訂單id生成規則不容易破解。防止黑客根據算法算到公司的一天的承單量。

2   分庫分表&擴容問題

                  2.0   垂直分庫分表

                                               按照業務拆分的方式稱爲垂直分片,又稱爲縱向拆分,它的核心理念是專庫專用。 在拆分之前,一個數據庫由多個數據表構成,每個表對應着不同的業務。而拆分之後,則是按照業務將表進行歸類,分佈到不同的數據庫中,從而將壓力分散至不同的數據庫。 下圖展示了根據業務需要,將用戶表和訂單表垂直分片到不同的數據庫的方案。

               垂直分片往往需要對架構和設計進行調整。通常來講,是來不及應對互聯網業務需求快速變化的;而且,它也並無法真正的解決單點瓶頸。 垂直拆分可以緩解數據量和訪問量帶來的問題,但無法根治。如果垂直拆分之後,表中的數據量依然超過單節點所能承載的閾值,則需要水平分片來進一步處理。

                           ps:垂直分片常見的分片規則以時間維度分表策略

                    2.1 分庫分表規則

                                           目前採用的是sharding-jdbc的PreciseShardingAlgorithm,用於處理使用單一鍵作爲分片鍵的=與IN進行分片的場景。需要配合StandardShardingStrategy使用。

                                      分庫規則:  user_id%數據源個數

                                      分表規則:  user_id/數據源個數 % 表個數   

                                   

                    2.3 分庫分表擴容 

擴容步驟:

1)等待ds_0_主和ds_1_主的數據同步到其備服務器,即ds_0_從和ds_1_從。 
2)停止寫服務,等待主備完全同步後解除ds_0_主與ds_0_從、ds_1_主與ds_1_從之間的主備關係。 
3)修改中間層的映射規則。 
4)開啓寫服務,用戶id哈希值模4等於0、1、2、3的數據將分別寫入到ds_0、ds_1、ds_2、ds_3。
5)分別給ds_0、ds_1、ds_2、ds_3增加從庫。
 

                        

【問題】我們爲什麼要選擇走按用戶維度做爲分片鍵,而不是從訂單維度來做?

1、對於C端用戶來說,用戶都是在登錄之後,再去查詢訂單,按用戶維度分片之後,相同用戶的訂單數據,都會落到同一個數據庫的同一個表中,

這樣用戶查詢自己的訂單的時候,可以不用跨庫操作,減輕服務壓力。

2、對以後跟用戶中心做交互的時候,都從用戶的角度來做,對接起來會比較容易

3、對於toB和toG的多維多查詢來說,我們可以在es中建立一層映射關係來應對。

3  訂單C端查詢&B端查詢&保存

                    3.0 c端用戶查詢邏輯

                     3.1 B端用戶查詢邏輯

4  redis緩存處理流程圖

          4.1 讀緩存處理流程圖

                       

         4.2 寫緩存處理流程圖

 

           redis&db數據一致性保證     

         循環2次更新緩存操作,直到更新成功退出循環,這一步主要能減小由於網絡瞬間抖動導致的更新緩存失敗的概率。對於緩存接口長時間不可用,靠循環調用更新接口是不能補救接口調用失敗的。如果循環2次還沒有更新成功,發送redis更新失敗埋點

      4.3  緩存代碼示例:

             4.3.1 獲取訂單詳情(讀更新緩存)

             4.3.2 更新or同步訂單(更新訂單refresh訂單緩存)

5 訂單配置中心

        5.1 添加Apollo客戶端依賴


<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.6.0</version>
</dependency>

       5.2 application.yml添加以下配置

app-id: apollo創建項目時的appid

apollo.meta: meta-server地址,一般同config-server地址
apollo.bootstrap.namespaces: 使用配置的命名空間,多個以逗號分隔

   ps: 我們會在打包的時候替換#param#如下設置

apollo具體安裝詳見: https://gitee.com/lepdou/apollo/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章