【netcore基础】ConcurrentDictionary 使用字符串作为key给代码加锁且使用EF事物防止并发调用数据混乱的问题

业务场景需要锁住指定的字符串下的代码,防止并发创建多个订单

 

这里我们使用

ConcurrentDictionary

 

首先初始化一个字典

private static readonly ConcurrentDictionary<string, string> _dictLock = new ConcurrentDictionary<string, string>();

 

然后使用定义一个要锁代码的的key,这里为保证每个订单唯一,使用微信的订单号作为key

 

对同一微信支付订单的回调进行加锁处理代码

            var lockkey = "wxpay_callback_lock_" + MD5Helper.GetMD5Str(pay.out_trade_no + pay.transaction_id); ;

            lock (_dictLock.GetOrAdd(lockkey, lockkey))
            {
                if (GeduRedisHelper.Exists(lockkey))
                {
                    throw new GeduException("操作正在处理,请勿重复请求");
                }

                GeduRedisHelper.Add(lockkey, new
                {
                    pay.out_trade_no,
                    pay.transaction_id

                }, 60);
            }

 

在lock代码段里我们使用 redis 来判断是否存在,为了方便以后分布式部署多台服务器的并发问题,这里可以redis共享key

 

然后在需要写入多个表的地方添加 事物处理

 using (var _trs = _orderService.GetDB().BeginTransaction())
            {
                try
                {

                    //todo...
                    
                    _trs.Commit();
                }
                catch (Exception ex)
                {
                    _trs.Rollback();

                    throw new GeduException(ex.Message);
                }
                finally
                {
                    GeduRedisHelper.Remove(lockkey);
                }

 

这样可以防止数据部分成功部分失败的问题

 

最后操作成功之后要清理掉 redis 里的lock

 

posted @ 2019-01-04 17:47  0539  阅读(1252)  评论(0编辑  收藏  举报