EF+Redis(StackExchange.Redis)实现分布式锁,自测可行
电商平台 都会有抢购的情况,比如 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