业务场景需要锁住指定的字符串下的代码,防止并发创建多个订单
这里我们使用
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