原文:.net core 下的分布式事务锁

系统分布式锁的用法

公司框架新增功能分布式锁:

锁的性能之王: 缓存 > Zookeeper >= 数据库

锁的实现

实现原理:核心采用StackExchange.Redis的LockTake方法实现。

支持同步获取锁,或者等待直到超时获取锁。

/// <summary>
/// 分布式锁,提供全局分布式锁支持,以resource redis为基础
/// 这个锁只能通过RpcContext来获取,通过自己手动释放
/// </summary>
public sealed class DistributedLock
{
private static readonly TimeSpan DefaultAbandonmentCheckFrequency = TimeSpan.FromSeconds(2); public readonly string lockName;
private readonly string lockValue;
private readonly int checkTimeSpan = 50; //ms
private readonly int autoDelete; private DistributedLock()
{
} /// <summary>
///
/// </summary>
/// <param name="lockName"></param>
/// <param name="autoDelete">自动删除,ms,默认 60s</param>
/// <param name="checkTimeSpan">如果不能获取锁,重复检查间隔:默认 50ms</param>
internal DistributedLock(string lockName, int autoDelete = 60000,int checkTimeSpan = 50)
{
// note that just Global\ is not a valid name
if (string.IsNullOrEmpty(lockName))
throw new ArgumentNullException("lockName不能为空"); if (null == ResourceCache.Instance)
throw new Exception(@"ResourceCache 没有配置或无法连接"); this.checkTimeSpan = Math.Max(checkTimeSpan,1);
this.autoDelete = Math.Max(autoDelete,1);
this.lockName = lockName;
this.lockValue = lockName;
} /// <summary>
/// 获取锁
/// </summary>
/// <param name="timeout">超时为null,则尝试一次即返回</param>
/// <returns>获取锁成功?</returns>
internal bool Acquire(TimeSpan? timeout = null)
{
bool bLock = false;
var dtStart = DateTime.Now.Ticks;
while (!bLock)
{
bLock = TryAcquireOnce();
if (timeout == null)
{
break;
}
if (!bLock)
{
Thread.Sleep(this.checkTimeSpan);
} var ts = new TimeSpan(DateTime.Now.Ticks - dtStart);
if (ts >= timeout)
{
break;
}
} return bLock;
}
//此处采用框架上下文管理分布式事务锁的释放,代码略。
//public void Dispose()
//{
// LockManager.ReleaseLock(this);
//} internal void Release()
{
try
{
var bRtn = ResourceCache.Instance.LockRelease(this.lockName, this.lockValue);
Trace.WriteLine($"释放锁 {this.lockName}:{bRtn}");
}
catch (Exception e)
{
LogTextWriter.Write($"释放锁失败,系统自动超时释放:{this.lockName}");
}
} /// <summary>
/// 释放锁
/// </summary>
public void ReleaseLock()
{
LockManager.ReleaseLock(this);
} private bool TryAcquireOnce()
{
try
{
Trace.WriteLine($"{Thread.CurrentThread.ManagedThreadId}:TryAcquireOnce");
var @lock = ResourceCache.Instance.LockTake(this.lockName, this.lockValue, new TimeSpan(0, 0, 0, 0, this.autoDelete));
return @lock;
}
catch (Exception e)
{
return false;
}
} }

锁的使用

在当前上下文中获取一个分布式锁,第一个获取锁的将执行依赖当前key(一般为业务主键)的完整业务流程(包括多个微服务之间的调用和数据库的访问;

后来者将无法获取锁,根据返回的结果来判断是否进入流程,如果返回的锁为null将不能执行下面的流程,要么重试等待锁释放,要么返回错误.

锁的调用一般流程:

        var qtLock=TryGetLock(lockKey);
if(qtLock==null)
{
//提示不能同时执行操作
return;
}
else
{
//进行业务流程
}
//最后别忘了
qtLock.ReleaseLock();

API内的范例:

 code = StatusCode.OK;

 //传入超时时间,可以一直等待到超时过期
var lockSaveReceipt = this.Context.TryGetLock($"{nameof(SaveReceipt)}.{valueArgs.ReceiptArgs.ReceiptId}");
if (lockSaveReceipt == null)
{
code = PublicErrorCode.SaveReceiptByUsed.ToCode();
return null;
} try{
//todo 业务操作1
//todo 业务操作2
//...
}
finally
{
lockSaveReceipt.ReleaseLock();
}

在此我向大家推荐一个微服务架构学习交流群。交流学习群号:864759589 里面会分享一些资深架构师录制的视频录像:高并发、高性能、分布式、微服务架构的原理,分布式架构等这些成为架构师必备的知识体系。


引用链接

  1. 口袋代码仓库
  2. 在线计算器
  3. 本节源码:github

.net core 下的分布式事务锁的更多相关文章

  1. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  2. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  3. 【转】.NET Core 事件总线,分布式事务解决方案:CAP

    [转].NET Core 事件总线,分布式事务解决方案:CAP 背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用 ...

  4. .net core 自带分布式事务的微服务开源框架JMS

    事务的统一性是微服务的一个重点问题,简洁有效的控制事务,更是程序员所需要的.JMS的诞生,就是为了更简单.更有效的控制事务. 先看一段调用微服务的代码: using (var ms = new JMS ...

  5. asp.net core集成CAP(分布式事务总线)

    一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...

  6. Asp.Net Core&CAP实现分布式事务

    需要注意的是标题中的CAP不是指的CAP理论,而是园区大神杨晓东实现的框架,CAP框架基于本地消息表用最终一致性实现分布式事务. 本地消息表 首先我们考虑一个场景,在将用户信息更改后,需要发送一条消息 ...

  7. .NET Core 事件总线,分布式事务解决方案:CAP

    背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用的过程中也会遇到分布式事务的问题,那么 CAP 就是在这样的背景 ...

  8. .NET Core 事件总线,分布式事务解决方案:CAP 基于Kafka

    背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用的过程中也会遇到分布式事务的问题,那么 CAP 就是在这样的背景 ...

  9. 记一个Redis分布式事务锁

    package com.mall.common; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory. ...

随机推荐

  1. 使用差分VHD启动Win7

    平台:windows 8.1 目的:在VHD里装个Win7 介绍:建立VHD装系统姑且不表,比较有意思的是用差分VHD备份系统这点. 差分硬盘这个概念在虚拟机里常用,类似VM中的快照,不过差分硬盘更灵 ...

  2. iterm恢复默认设置

    命令行执行以下命令即可: defaults delete com.googlecode.iterm2

  3. 前端面试题(VUE)

    (前端面试题大全,持续更新) vue:v-model 双向绑定的原理 依赖收集 虚拟DOM的作用 vue@3.0中的preset配置? 父组件A和其子组件B/子组件C,B/C进行通信的方式(怎么通信) ...

  4. Flask项目之手机端租房网站的实战开发(十一)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

  5. ANSI转UTF-8中文无乱码解决方案

    近期做的项目需要使用Doxygen生成文档,由于前期代码不是本人完成,他使用的是ANSI格式的文件,后来我用Notepad++写其他文件时,默认保存为UTF-8 无BOM编码格式,因此整个项目文件中既 ...

  6. Javascript和jquery事件--事件对象event

    1.  事件对象event 对于event,js的解释是Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态.而jq的解释是事件处理(事件对象.目标元素 ...

  7. 多类 SVM 的损失函数及其梯度计算

    CS231n Convolutional Neural Networks for Visual Recognition -- optimization 1. 多类 SVM 的损失函数(Multicla ...

  8. 对inetd、xinetd与TCP_Wrapper的基本了解

    在Linux系统中有一个特殊的守护进程inetd(InterNET services Daemon),它用于Internet标准服务,通常在系统启动时启动.通过命令行可以给出inetd的配置文件,该配 ...

  9. jtag引脚

    如果不能下载,可能原因也许是电量不足了... 在电力不足的时候,仿真也不能进行... ///////////////////////////////////////////////////////// ...

  10. swift项目第六天:中间发布按钮的封装以及监听点击事件

    import UIKit /* 总结:1:给UIButton写分类,新建文件swiftFile,一般为了区分起名字都是名字-Extension,要想调用UI控件需要导入 import UIKit框架, ...