.netcore 微服务快速开发框架 Anno&Viper -分布式锁是个什么鬼
1、什么是锁
锁是为了解决多线程或者多进程资源竞争的问题。
同一进程的多个线程资源竞争可以用lock解决。
lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
class Test
{
//定义一个私有成员变量,用于Lock
private static object lockobj = new object();
void DoSomething()
{
lock (lockobj)
{
//需要锁定的代码块
}
}
}
多进程之间解决资源竞争问题我们则需要引入分布式锁。通过一个协调者来解决,通常的解决办法是通过redis来解决,这里不展开redis分布式锁的讨论。 接下来我们来聊聊如何自己实现一个分布式锁(不依赖于redis)。
2、分布式锁是个什么鬼
分布式锁是分布式、微服务中一个必然要讨论的话题。他为的是解决多进程多线程资源竞争的问题。
下面我们以订单系统下单扣减库存为例聊一聊扣减库存的问题。
三个客户KA、KB、KC同时下单购买物品P1,请求通过负载均衡器分发到订单服务A、订单服务B、订单服务C。这个时候三个服务同时要对数据库中的P1物品判断库存是否充足。假设库存剩余10个,KA需要购买6个、KB需要购买6个、KC需要购买6个。
正常情况下服务A、B、C都查询了库存大于购买的数量,那么三个服务都判断可以下单。此时我们可以看到,她们都进行下单明显剩余库存不足18个,那么就会出现超卖的问题。那我们怎么办。我们第一时间会想到锁,不过在分布式环境下程序自带的Lock已经不能解决我们的问题。
消息队列也可以解决这个问题,不过这里我们不讨论,我们要讨论的是用锁来解决。
这个时候我们需要一个协调者来协调三个服务同时只能有一个请求进入下单代码块。原理同本地锁一样(当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放)。另外我们还需要注意的是,如果锁的拥有者出现问题,不能及时释放锁。那么就会导致其他服务一直等待。那么就会出现死锁的问题,因此我们也必须一如超时机制。在我们预设的处理时间内不能释放锁则需要协调者自动释放锁。防止出现死锁。
下面我们来看看微服务框架Anno是如何实现一个分布式锁。
如果对Anno微服务框架不了解可以看这里《【开源】.net微服务开发引擎Anno开源啦》
2、实现一个分布式锁
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; namespace ConsoleTest
{
using Anno.Const;
using Anno.EngineData;
using Anno.Loader;
using Anno.Rpc.Client;
using Anno.Rpc.Server;
using Autofac; public class DLockTest
{
public void Handle()
{
Init();
To:
List<Task> ts = new List<Task>();
Console.WriteLine("请输入线程数:");
int.TryParse(Console.ReadLine(), out int n);
for (int i = 0; i < n; i++)
{
var task = Task.Factory.StartNew(() => { DLTest1("Anno"); });
ts.Add(task);
//var taskXX = Task.Factory.StartNew(() => { DLTest1("Viper"); });
//ts.Add(taskXX); //var taskJJ = Task.Factory.StartNew(() => { DLTest1("Key001"); });
//ts.Add(taskJJ);
} Task.WaitAll(ts.ToArray());
goto To;
} private void DLTest1(string lk = "duyanming")
{
try
{
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1拉取锁({lk})");
using (DLock dLock = new DLock(lk, 10000))
{
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1进入锁({lk})");
System.Threading.Thread.Sleep(50);
} Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1离开锁({lk})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
void Init()
{
//SettingService.AppName = "DLockTest";
//SettingService.Local.IpAddress = "127.0.0.1";
//SettingService.Local.Port = 6660; IocLoader.GetAutoFacContainerBuilder().RegisterType(typeof(RpcConnectorImpl)).As(typeof(IRpcConnector)).SingleInstance();
IocLoader.Build();
DefaultConfigManager.SetDefaultConnectionPool(100, Environment.ProcessorCount * 2, 50);
DefaultConfigManager.SetDefaultConfiguration("DLockTest", "127.0.0.1", 6660, false);
}
}
}
GitHub地址:https://github.com/duyanming/Anno.Core/blob/master/test/ConsoleTest/DLockTest.cs
不同类型的锁可以同时进入相互不影响
var task = Task.Factory.StartNew(() => { DLTest1("Anno"); });
ts.Add(task);
var taskXX = Task.Factory.StartNew(() => { DLTest1("Viper"); });
ts.Add(taskXX); var taskJJ = Task.Factory.StartNew(() => { DLTest1("Key001"); });
ts.Add(taskJJ);
上图我们开了12个进程同时进入DLTest1 方法,
using (DLock dLock = new DLock(lk, 10000))设置超时时间10秒。
关键代码:
private void DLTest1(string lk = "duyanming")
{
try
{
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1拉取锁({lk})");
using (DLock dLock = new DLock(lk, 10000))
{
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1进入锁({lk})");
System.Threading.Thread.Sleep(50);
} Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff} {System.Threading.Thread.CurrentThread.ManagedThreadId} DLTest1离开锁({lk})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
所有源码都可以在 Anno中找到。
Anno核心源码:https://github.com/duyanming/Anno.Core
Viper示例项目:https://github.com/duyanming/Viper
体验地址:http://140.143.207.244/Home/Login
QQ交流群:478399354
.netcore 微服务快速开发框架 Anno&Viper -分布式锁是个什么鬼的更多相关文章
- .netcore 微服务快速开发框架 Anno&Viper 注册中心 (服务上线下线预警通知)
1.微服务时代,服务上线先预警通知 在微服务大行其道的今天,相信很多人都用上了微服务或者是微服务的概念也已经有了一个深刻的了解.今天我们不在这里展开阐述,今天我们要说的是微服务伴侣预警通知. 2.注册 ...
- Anno&Viper -分布式锁服务端怎么实现
1.Anno简介 Anno是一个微服务框架引擎.入门简单.安全.稳定.高可用.全平台可监控.依赖第三方框架少.底层通讯RPC(Remote Procedure Call)采用稳定可靠经过无数成功项目验 ...
- 不死的小强 .net core 微服务 快速开发框架 Viper 限流
1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...
- net core 微服务 快速开发框架 Viper 初体验2020-10-17
1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...
- 基于SpringBoot-Dubbo的微服务快速开发框架
简介: 基于Dubbo的分布式/微服务基础框架,为前端提供脚手架开发服务,结合前一篇--Web AP快速开发基础框架,可快速上手基于Dubbo的分布式服务开发,项目代码: https://github ...
- net core 微服务 快速开发框架
dymDemo github 地址:https://github.com/duyanming/dymDemo dym 分布式开发框架 Demo 熔断 限流 事件总线(包括基于内存的.rabbitmq的 ...
- 一个轻量级的.Net Core微服务快速开发的轮子
前言 Adnc是一个轻量级的.Net Core微服务快速开发框架,同时也可以应用于单体架构系统的开发.框架基于JWT认证授权.集成了一系列微服务配套组件,代码简洁.易上手.学习成本低.开箱即用 ...
- .NETCore微服务探寻(三) - 分布式日志
前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...
- (1)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 什么是微服务架构,.netCore微服务选型
开发工具:VS2017 .Net Core 2.1 什么是微服务?单体结构: 缺点: 1)只能采用同一种技术,很难用不同的语言或者语言不同版本开发不同模块: 2)系统耦合性强,一旦其中一个模块有问题, ...
随机推荐
- 第11.27节 Python正则小结:正则静,静则明,明则虚,虚则无为而无不为也
正则表达式的章节到此就结束了,老猿现在觉得对我们这些身具程序猿基因特色的人来说,正则表达式应该是蛮可口的开胃小菜. 在写标题时,本来想写"正则表达式小结",后来想了想,百度了一下, ...
- PyQt(Python+Qt)学习随笔:QHeaderView的CascadingSectionResizes属性
老猿Python博文目录 老猿Python博客地址 一.CascadingSectionResizes作用 QHeaderView的CascadingSectionResizes属性用于控制当用户调整 ...
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的windowIcon属性
windowIcon对象为部件对象的属性,但只有窗口对象有效,其他派生对象如pushButtong对象无效. 在windowIcon对象上有如下子属性设置: 这几个子属性实际上是QIcon类中继承的. ...
- PHP代码审计分段讲解(11)
后面的题目相对于之前的题目难度稍微提升了一些,所以对每道题进行单独的分析 27题 <?php if(!$_GET['id']) { header('Location: index.php?id= ...
- MySQL-索引分类及使用索引
1.什么是索引? 索引:存储引擎用于快速找到记录的一种数据结构,默认使用B-Tree索引.索引是存储引擎层中实现.简单理解为:排好序的快速查找数据结构 索引的目的:提高数据查询的效率,优化查询性能,就 ...
- Python-Wechaty: 面向所有IM软件的聊天机器人框架
Author: wj-Mcat Code: python-wechaty 个人开发项目,且行且不易,有感兴趣的朋友可以去给一波关注,你们的支持就是我最大的动力,谢谢大家. Python-wechaty ...
- Java堆内存中为什么有两个survival区及为什么与年轻代比例是1:1:8?
Java堆内存分为年轻代和老年代,其中,年轻代分为Eden区和survival区,survival又分为fromSurvival和toSurvival. 首先第一个问题:为什么要有Survival区? ...
- 安卓11配置谷歌FCM推送报错
2020-12-11 11:57:50.872 15404-15464/com.sp.notify E/FirebaseInstanceId: Failed to get FIS auth token ...
- asp.net-ajax使用-WebMethod使用
1.js $.ajax({ type: "POST", contentType: "application/json", url: "activity ...
- DVWA各等级XSS
xss原理及基本介绍 XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器 ...