優(yōu)極限【完整項目實戰(zhàn)】半天帶你用-springBoot、Redis輕松實現(xiàn)Jav

秒殺功能設計:
- 秒殺起止時間與動態(tài)倒計時、商品原價與秒殺價、商品秒殺庫存、“秒殺”按鈕的置灰與秒殺進行中的設計
- 秒殺的兩個判斷:
- 庫存夠不夠(DB中去查而不是相信前端)
- 用戶僅限購一件,根據(jù)t_seckill_order表的user_id和goods_id兩個屬性是否重復從而判斷他是否有超購行為
- 注意秒殺商品扣減庫存時,要同時生成訂單和秒殺訂單,因為秒殺訂單表的訂單id和訂單表的id是外鍵關聯(lián)的
引入Jmeter秒殺接口性能:
?
028_JMeter簡單使用 P28 - 07:00
?QPS:Query/s,比如:對一個頁面訪問的請求數(shù)
TPS:Transaction/s,比如:請求-查詢-響應三個階段,tps就是3
- 不同的用戶訪問商品列表接口
- 不同的用戶訪問秒殺接口(這是要更新DB的?。。òl(fā)生的問題:慢、商品超賣)
壓測后秒殺接口性能優(yōu)化:
- 頁面緩存:添加讀寫多更新少數(shù)據(jù)的緩存
- Redis、商品列表頁面、rul緩存本質還是頁面緩存
- 如果商品量足夠大,幾百幾千頁,頁面緩存可能也就是幾十頁甚至幾頁
- 優(yōu)化效果:較優(yōu)化前qps提升了1倍
- 對象緩存
- 處理分布式session時,用redis緩存了用戶信息,根據(jù)cookie獲取user,而user信息往往不會更改。即使更改也是極少部分,且為了保證用戶數(shù)據(jù)信息DB和緩存的一致性,可以延遲雙刪策略
- 頁面靜態(tài)化(拆分頁面)
- 商品列表頁面
- 秒殺頁面
- 訂單詳情頁面
- 靜態(tài)資源的優(yōu)化
- CDN優(yōu)化
- 庫存超賣
- 扣減庫存前肯定是要根據(jù)用戶id和商品id去查商品數(shù)夠不夠,那么可將兩個id作為聯(lián)合唯一索引,用以防止一個用戶多次搶購的問題
- 細小優(yōu)化:將秒殺訂單信息放到緩存里便于處理(總的性能提升2倍,主要是因為庫存賣完后,庫存信息放到redis中就不更新了,用戶來搶購時就只走redis而不走DB)
- 優(yōu)化過程中仍然出現(xiàn)的問題:10件秒殺商品庫存沒有超賣,但是訂單卻生成了90個(SQL解決的:庫存減一+條件庫存>0)
?
044_接口優(yōu)化方向 P44 - 04:33
?優(yōu)化總結:
- 引入緩存
- 3個頁面緩存
- 對象緩存
- 3個頁面靜態(tài)化
- 重點解決超賣問題:
- 加索引防止同一用戶多次購買
- sql:update table set stock=stock-1 where stock>0
- 高并發(fā)情形下再次優(yōu)化--接口優(yōu)化:
- redis預減庫存,減少對DB的訪問
- 即使redis預減庫存,DB仍要交互,高并發(fā)情形下咋辦?優(yōu)化下單可用Rabbit MQ隊列,緩沖與異步下單
- redis自己也是服務器,單獨部署仍有優(yōu)化空間:內(nèi)存標記
- 整體優(yōu)化思路:先將秒殺商品信息存放到redis里,用戶點擊秒殺后,判斷有庫存則給用戶響應“訂單排隊中”,并將此扣減庫存的請求放到Rabbit MQ里,異步生成訂單,出單成功后通過輪詢方式給響應用戶下單成功或失敗。(分庫分表、DB集群在適當時也可考慮)
- 加載庫存
- 預減庫存
- 庫存不足直接返回;庫存足夠則封裝請求到MQ
- 后端返回排隊中
- 消息出隊進行真實扣減庫存
- 將成功或失敗的消息通過MQ返回給用戶
?
052_Redis預減庫存 P52 - 05:55
?- 實現(xiàn)初始化Bean時將DB數(shù)據(jù)加載到Redis中,實現(xiàn)InitializingBean接口,重新afterPropertiesSet方法;預減庫存時,為了保證原子性,用了redis的decrement方法,加上庫存數(shù)量大于0的邏輯可以使得高并發(fā)情況下庫存不會扣減為負數(shù)。(這里也可以用redis鎖,異常不能刪鎖--->配置超時時間;會出現(xiàn)連環(huán)刪鎖怎么辦?--->多個命令一次執(zhí)行---lua腳本,兩種實現(xiàn)方式你選哪個?)面試可以說說
- 內(nèi)存標記、前端輪詢獲取數(shù)據(jù)
- redis分布式鎖優(yōu)化項目:lua不放客戶端會大幅降低qps
- ThreadLocal
- 主流企業(yè)解決方案:
- 搶購預約
- 網(wǎng)關限流
- 分布式鎖 性能不太行
標簽: