電商平台 都會有搶購的情況,比如 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
