- 多應用實例全局唯一訂單號
- 分庫分表&擴容問題
- 訂單C端查詢&B端查詢&保存
- 訂單緩存設計&3萬+qps
- 訂單配置中心
- 訂單狀態機
- 訂單熔斷&降級
1 多應用實例全局唯一訂單號(按時間趨勢遞增,訂單id帶有業務標示)
xx-snowflake簡介
改造版 xx-snowflake方案採用“1+5+41+5+12”的方式組裝ID號,使用Zookeeper持久順序節點的特性自動對snowflake節點配置wokerID。 xx-snowflake是按照下面幾個步驟啓動的:
- 啓動Leaf-snowflake服務,連接Zookeeper,在leaf_forever父節點下/snowflake/order-center/forever/檢查自己是否已經註冊過(是否有該順序子節點)。(workerid:/snowflake/order-center/forever/192.168.17.197:2181-0000000000)
- 如果有註冊過直接取回自己的workerID(zk順序節點生成的int類型ID號),啓動服務。
- 如果沒有註冊過,就在該父節點下面創建一個持久順序節點,創建成功後取回順序號當做自己的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/