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