電商平臺 都會有搶購的情況,比如 1元搶購。 而搶購 最重要的 就是庫存,很多情況下 庫存處理不好,就會出現超賣現象。 本文將用redis為緩存,StackExchange 框架,消息隊列方式 實現分散式鎖的情況 一,效果 先看效果, 窗體下單 構建高併發情況 開多個控制台應用程式 處理訂單 二,配 ...
電商平臺 都會有搶購的情況,比如 1元搶購。 而搶購 最重要的 就是庫存,很多情況下 庫存處理不好,就會出現超賣現象。
本文將用redis為緩存,StackExchange 框架,消息隊列方式 實現分散式鎖的情況
一,效果
先看效果,
窗體下單 構建高併發情況
開多個控制台應用程式 處理訂單
二,配置Redis
<Redis.Service> <DbConfig Name="Order_DBName" Hosts="127.0.0.1:6379" dbNum="2"> </DbConfig> <DbConfig Name="Product_DbName" Hosts="127.0.0.1:6379" dbNum="1"> </DbConfig>
模擬用戶下單
private void button1_Click(object sender, EventArgs e) { var orderCount = Convert.ToInt32(txt_OrderCount.Text); var productId = Convert.ToInt32(txt_ProductId.Text); var productCount = Convert.ToInt32(txt_ProductCount.Text); for (int i = 0; i < orderCount; i++) { RedisOrderModel cacheOrder = new RedisOrderModel() { Count = productCount, OrderNo = (orderNo += 1).ToString(), ProductId = productId }; orderRedis.Push(cacheOrder); } }
控制台程式 處理訂單
public void QueueList() { RedisOrderMessage redis = new RedisOrderMessage(); while (true) { try { var cacheOrder = redis.Pop(); if (cacheOrder == null) { Console.WriteLine("無訂單,休息100毫秒"); Thread.Sleep(1000); continue; } while (ThreadCount<=0) { Console.WriteLine("線程已滿,休息100毫秒"); Thread.Sleep(100); } //ThreadCount--; Thread thread = new Thread(new ThreadStart(cacheOrder.CreateOrder)); thread.Start(); Console.WriteLine("正在處理訂單,休息100毫秒"); Thread.Sleep(100); } catch (Exception ex) { Console.WriteLine(ex.Message + "," + ex.StackTrace); Thread.Sleep(1000); } finally { ThreadCount++; } } }
使用分散式鎖,判斷庫存是否足夠
public void LockStore(string productId, int count) { var keyInfo = AddSysCustomKey(productId); if (!Exists(keyInfo)) { throw new Exception("商品緩存緩存不存在"); } var redisConfig = ReadRedisConfig.GetRedisConfig(DB_Name); var lockdb = redisConfig.GetDatabase(-1); var db = redisConfig.GetDatabase(); var token = Environment.MachineName; while (true) { //db.LockRelease(keyInfo, token); var con = lockdb.LockTake(keyInfo, token, TimeSpan.FromSeconds(10.0), CommandFlags.None); //var con = db.LockTake(keyInfo, token, TimeSpan.FromSeconds(20), CommandFlags.None); if (con) { try { var product = ConvertObj<CacheProduct>(db.StringGet(keyInfo)); if (product.Count < count) { throw new Exception("數量不夠,下單失敗"); } product.Count -= count; var json = ConvertJson(product); db.StringSet(keyInfo, json); } finally { lockdb.LockRelease(keyInfo, token); } break; } } }
源碼地址:
https://github.com/buruainiaaaa/CacheDemo.git