設計一個支援高併發的分散式鎖,商品維度
try {
Boolean product = redisTemplate.opsForValue().setIfAbsent("product-test001", "1", 11, TimeUnit.SECONDS);
if (null == product) {
// 自旋
while (true) {
System.out.println("自旋開始" + Thread.currentThread().getName());
Thread.sleep(4000L);
// 加鎖成功
if (null != redisTemplate.opsForValue().setIfAbsent("product-test001", "1", 11, TimeUnit.SECONDS)) {
// 扣減庫存
System.out.println("自旋扣減庫存開始" + Thread.currentThread().getName());
Thread.sleep(10000L);
System.out.println("自旋扣減庫存成功" + Thread.currentThread().getName());
break;
}
}
}
// 扣減庫存 模擬扣減庫存
Thread.sleep(10000L);
} finally {
// 防止異常情況 必須釋放鎖
redisTemplate.delete("product-test001");
}
自旋開始http-nio-8081-exec-1
自旋開始http-nio-8081-exec-4
自旋開始http-nio-8081-exec-1
自旋開始http-nio-8081-exec-4
自旋開始http-nio-8081-exec-1
自旋扣減庫存開始http-nio-8081-exec-4
自旋開始http-nio-8081-exec-1
自旋開始http-nio-8081-exec-1
自旋扣減庫存成功http-nio-8081-exec-4
自旋開始http-nio-8081-exec-1
自旋扣減庫存開始http-nio-8081-exec-1
自旋扣減庫存成功http-nio-8081-exec-1
看上去好像沒有什麼問題
場景1.在整個程式碼塊中發生異常了,就比如第一個setNx的時候超時了,可能有很多原因比如大的bigkey、比如很多很多的請求突然打到web,那麼這個時候就會發生直接去finally ,釋放了鎖。那麼在後續購買商品的請求訪問時,鎖失效 !
解決思路:使用執行緒的value進行比較,只有是本執行緒的加鎖的才能釋放。
那麼這個時候又有一個問題,假設這個執行緒因為操作庫存某些問題導致死了,那程式不就也死了?
設定了redis的超時時間,假設這個商品不能扣減庫存了,那也就這10秒不能操作,網際網路公司的業務完全能接受。
String threadId = String.valueOf(Thread.currentThread().getId());
try {
// 獲取庫存數量 40
Boolean product = redisTemplate.opsForValue().setIfAbsent("product-test001", threadId, 11, TimeUnit.SECONDS);
if (null == product) {
// 自旋
while (true) {
System.out.println("自旋開始" + Thread.currentThread().getName());
Thread.sleep(4000L);
// 加鎖成功
if (null != redisTemplate.opsForValue().setIfAbsent("product-test001",threadId, 11, TimeUnit.SECONDS)) {
// 扣減庫存
System.out.println("自旋扣減庫存開始" + Thread.currentThread().getName());
Thread.sleep(10000L);
System.out.println("自旋扣減庫存成功" + Thread.currentThread().getName());
break;
}
}
}
// 扣減庫存 模擬扣減庫存
Thread.sleep(10000L);
} finally {
if(threadId.equals(redisTemplate.opsForValue().get("product-test001"))){
// 防止異常情況 必須釋放鎖
redisTemplate.delete("product-test001");
}
}
因為這款商品是爆品所以導致一旦開啟會有超高併發的可能存在,這個時候就會對redis的壓力非常大,怎麼設計?
使用分段鎖思想,比如將product_test1分成product_test1_001,product_test1_002,...,product_test1_100 根據某種規則讓他坐落在叢集的不同的槽位中 ,假設有10個叢集節點那麼,16384/10 儘量坐落在不同的節點,可以大幅度提高redis的吞吐量。
相關文章
- 「如何設計」高可用的分散式鎖分散式
- [分散式]架構設計原則--高併發分散式架構
- [分散式][高併發]高併發架構分散式架構
- 分散式鎖--高併發優化實踐(分段加鎖思想)!分散式優化
- 高併發服務端分散式系統設計概要服務端分散式
- 高併發核心技術 - 冪等性 與 分散式鎖分散式
- 高併發架構系列:分散式鎖的由來、特點及Redis分散式鎖的實現詳解架構分散式Redis
- 從零開始的高併發(二)--- Zookeeper實現分散式鎖分散式
- 【高併發】之分散式全域性唯一 ID分散式
- 「分散式技術專題」併發系列一:基於加鎖的併發控制分散式
- [分散式]對高併發流量控制的一點思考分散式
- [分散式][高併發]限流的四種策略分散式
- 併發程式設計之顯式鎖原理程式設計
- 高併發(鎖)
- 分散式鎖不是控制併發冪等的方式分散式
- 如何設計一個高可用、高併發秒殺系統
- 分散式死鎖的一個例子分散式
- 面試題:如何設計一個高併發系統?面試題
- 用分散式鎖解決併發問題分散式
- 《JAVA併發程式設計實戰》顯式鎖Java程式設計
- 分享一個整合SSM框架的高併發和商品秒殺專案SSM框架
- ZooKeeper 分散式鎖 Curator 原始碼 03:可重入鎖併發加鎖分散式原始碼
- 實現一個redis的分散式鎖Redis分散式
- 面試集錦(八)分散式與高併發面試分散式
- 【高併發】如何設計一個支撐高併發大流量的系統?這次我將設計思路分享給大家!
- 探索併發程式設計(七)——分散式環境中併發問題程式設計分散式
- 分散式鎖解決併發的三種實現方式分散式
- Laravel05電商實戰:一個小希望這本教程商品模組的商品SKU支援多維度設計,希望後面能夠對重點模組更加詳細設計Laravel
- 圖解Janusgraph系列-併發安全:鎖機制(本地鎖+分散式鎖)分析圖解分散式
- 高併發系統設計的15個錦囊
- Java併發程式設計-鎖及併發容器Java程式設計
- 實現一個 Redis 分散式鎖Redis分散式
- [分散式]高併發案例---庫存超發問題分散式
- jmeter介面效能測試-高併發分散式部署JMeter分散式
- Java對併發程式設計的支援Java程式設計
- 設計一個分散式RPC框架分散式RPC框架
- 分散式儲存高可用設計分散式
- 高併發設計筆記筆記