[日常] 高併發搶購方案的思考

来源:https://www.cnblogs.com/taoshihan/archive/2019/10/28/11754633.html
-Advertisement-
Play Games

經常在面試中被問到如何設計一個高併發環境下的搶購方案,雖然網上的資料已經很多了,但是都是很簡單的說了一些用隊列之類的套話,沒有更詳細的細節考慮.被問的實在是太多了,不得已我也仔細想想這些該怎麼設計.拋開運維階段的多層負載均衡,直接只說PHP的業務層面的邏輯. 整個流程如下:web界面點擊搶購==>彈 ...


經常在面試中被問到如何設計一個高併發環境下的搶購方案,雖然網上的資料已經很多了,但是都是很簡單的說了一些用隊列之類的套話,沒有更詳細的細節考慮.被問的實在是太多了,不得已我也仔細想想這些該怎麼設計.拋開運維階段的多層負載均衡,直接只說PHP的業務層面的邏輯.

整個流程如下:
web界面
點擊搶購==>彈出答題彈窗==>答對判定當前隊列長度==>隊列未滿就進入隊列,顯示排隊中(狀態),使用wbsocker實時關註用戶狀態
            ==>答錯再答基本就沒戲了返回失敗
                           ==>隊列滿了,返回失敗


後端進程
從隊列隨機取部分用戶==>修改他的狀態為待支付狀態===>用戶點擊支付進行判定庫存量===>支付完成減庫存

在整個過程中,用戶點擊支付的時候也要判定庫存,如果沒庫存就顯示失敗;用戶點擊完支付,庫存充足,如果隔了很長時間才輸入密碼支付,這個過程中如果庫存沒了,要給用戶退款;

也就是要麼冗餘部分商品,要麼給用戶退款兩種方案

 

商品的詳細信息
$redis->hGet('product', 'num','name');
商品數量設置的是10,其餘欄位留著存其他信息

用戶的狀態
1:答題狀態
2:排隊狀態
3:支付狀態
4:搶購成功!
5:搶購失敗

搶購介面:panic_buy.php
1.判定當前用戶哈希是否存在,如果不存在就設置一下
$redis->hSetNx('taoshihan', 'status', 1);
2.查看當前商品的庫存,如果為0直接返回失敗,更改用戶狀態為:5
$redis->hGet('product', 'num');
3.查看以下隊列長度,如果超過1000,直接更改用戶狀態為:5
$redis->lLen('panic_buying');
3.用戶進入隊列排隊,更改用戶狀態為:2
$redis->rPush('panic_buying', 'taoshihan');

查詢狀態:status.php
對於進入隊列成功的用戶才會調用到這個介面
1.判定當前用戶狀態
$redis->hGet('taoshihan', 'status');


支付介面:pay.php
1.判定當前用戶狀態
$redis->hGet('taoshihan', 'status');
2.判定當前商品數量,如果已經小於10個更改用戶狀態為:5
$redis->hGet('product', 'num');
3.支付完成修改當前商品數量
$redis->hIncrBy('product', 'num',-1);


後端進程:
獲取下商品數量,如果等於0,就把所有除去進入支付集合的隊列成員更改用戶狀態為:5
$redis->hGet('product', 'num');
$redis->sIsMember('pay', 'taoshihan');//是否存在於集合中

獲取前100個用戶,更改狀態為:3,把該用戶同時進入另一支付集合
$redis->lRange('panic_buying', 0, 99);//獲取前100個
$redis->sAdd('pay' , 'taoshihan');//插入支付集合


PHP-Redis擴展的哈希結構函數

hDel-刪除一個或多個哈希欄位
hExists-確定哈希欄位是否存在
hGet-獲取哈希欄位的值
hGetAll-獲取哈希中的所有欄位和值
hIncrBy-將哈希欄位的整數值增加給定數字
hIncrByFloat-將哈希欄位的浮點值增加給定數量
hKeys-獲取哈希中的所有欄位
hLen-獲取哈希中的欄位數
hMGet-獲取所有給定哈希欄位的值
hMSet-將多個哈希欄位設置為多個值
hSet-設置哈希欄位的字元串值
hSetNx-設置哈希欄位的值,僅當該欄位不存在時
hVals-獲取哈希中的所有值
hScan-掃描成員的哈希鍵
hStrLen-獲取與哈希中的欄位關聯的值的字元串長度

PHP REDIS擴展的列表的函數

blPop,brPop-刪除並獲取列表中的第一個/最後一個元素
bRPopLPush-從列表中彈出一個值,將其推到另一個列表中並返回
lIndex,lGet-通過列表從其索引中獲取元素
lInsert-在列表中的另一個元素之前或之後插入一個元素
lLen,lSize-獲取列表的長度/大小
lPop-刪除並獲取列表中的第一個元素
lPush-在列表前添加一個或多個值
lPushx-僅在列表存在時才在列表前添加值
lRange,lGetRange-從列表中獲取一系列元素
lRem,lRemove-從列表中刪除元素
lSet-通過其索引設置列表中元素的值
lTrim,listTrim-將列表修剪到指定範圍
rPop-刪除並獲取列表中的最後一個元素
rPopLPush-刪除列表中的最後一個元素,將其附加到另一個列表中並返回(redis> = 1.1)
rPush-將一個或多個值添加到列表
rPushX-僅在列表存在時將值附加到列表

PHP-Redis擴展集合的操作方法

sADD 添加一個或多個成員到集合裡面
sCard, sSize 獲取一下集合中成員的個數
sDiff 在N個集合中比較出差集
sDiffStore 和sDiff差不多,但是把差集結果存儲在第一個key裡面
sInter 返回多個集合的交集
sInterStore 和sInter類似,把結果存儲在第一個key裡面
sIsMember, sContains檢查參數中的成員是否是集合中的一員
sMembers, sGetMembers 獲得集合中的所有成員
sMove 把集合中的成員從一個集合移動到另一個集合
sPop 在集合中隨機刪除一個並獲取到這個成員
sRandMember 在集合中隨機獲取一個成員,並不刪除它
sRem, sRemove 在集合中刪除指定成員
sUnion 返回多個集合的並集
sUnionStore 把多個集合的並集存儲在第一個參數key裡面


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • (原創)C/C++語言, 平臺是debian10, grpc版本:grpc c++/1.25.0 dev, 使用的例子是自帶的例子GreeterClient 創建 default executor 和 resolver executor 線程的主要流程,創建channel時會創建這2個線程 grpc ...
  • Java 中 final、finally、finalize 有什麼不同?這是在 Java 面試中經常問到的問題,他們究竟有什麼不同呢? 這三個看起來很相似,其實他們的關係就像卡巴斯基和巴基斯坦一樣有基巴關係。 那麼如果被問到這個問題該怎麼回答呢?首先可以從語法和使用角度出發簡單介紹三者的不同: fi ...
  • 2019-10-28-22:40:14 目錄 1.Instanceof關鍵字 2.Final關鍵字 2.1Final關鍵字修飾類 2.2Final關鍵字修飾成員方法 2.3Final關鍵字修飾局部變數 2.4Final關鍵字修飾成員變數 3.許可權修飾符 Instanceof關鍵字 作用:判斷一個父類 ...
  • 一、XML文件寫入 1.更改 (1)ele.set:修改屬性 (2)ele.remove:刪除元素。 (3)ele.append:添加子元素。 我們舉個例子並且使用新建的XML和新學的方法 2.生成創建 subElement;etree創建; 三、源碼 D30_4_XmlSchool.xml D30 ...
  • MyBatis 的初始化工作就是解析主配置文件,映射配置文件以及註解信息。 ...
  • 函數初識 函數是一組操作的集合,並賦予它一個名字。你已經使用過許多 Python 內置的函數,例如 string.title() 和 list.sort() 。我們也可以定義自己的函數,它們可以“教導” Python 作一些新的行為 定義一個函數 使用關鍵字 def 告訴 Python 你將要定義一 ...
  • Dubbo 在 2011 開源之後,一直是國內最受歡迎的 RPC 框架,之後 Spring Boot 和 Spring Cloud 的面世,助推了微服務的火熱程度。電腦的世界變化很快,自從容器和 K8s 登上舞臺之後,給原有的 RPC 領域帶來了很大的挑戰。這個文章主要講述 RPC 領域遇到的問題... ...
  • 本人3年開發經驗、18年年底開始跑路找工作,在互聯網寒冬下成功拿到阿裡巴巴、今日頭條、滴滴等公司offer,崗位是Java後端開發,最終選擇去了阿裡巴巴。 面試了很多家公司,感覺大部分公司考察的點都差不多,所以將自己的心得記下來,希望能給正在找或者準備找工作的朋友提供一點幫助。另外,目前在阿裡也做面 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...