1、高并发的情况,时常会发生数据不稳定的情况

  在看本节内容之前,请先看上一章SqlServer 高并发的情况下,如何利用锁保证数据的稳定性

  本节内容,也是具体讨论如何在EF中实现这些操作

2、场景模拟,同上一章,抢券

  EF 不考虑高并发的情况下,抢券代码为:

string _currOwner = Console.ReadLine();//当前用户
using var ctx = new MyDBContext();
var cop = ctx.Coupons.Single(x => x.Id == 2);
if (!string.IsNullOrEmpty(cop.Owner))
{
Console.WriteLine($"券被抢了");
}
else
{
cop.Owner = _currOwner;
Thread.Sleep(5000);
ctx.SaveChanges();
Console.WriteLine($"恭喜{_currOwner}抢到券{cop.Id}了");
}
Console.ReadLine();

  打开两个进程,让tom和jerry同时先后进行抢券,模拟出一个券同时被两个用户抢到的情况

     

  上图可用直观看出,都提示抢券成功,但是owner是晚一点点执行update的jerry,在实际生产中,无法给tom一个交代

3、解决并发问题

  3.1 通过updlock,悲观并发控制

string _currOwner = Console.ReadLine();//当前用户
using var ctx = new MyDBContext();
using var tx = ctx.Database.BeginTransaction();
FormattableString sql = $@"select * from Coupons with(updlock) where id=2";
var cop = ctx.Coupons.FromSqlInterpolated(sql).Single();
if (!string.IsNullOrEmpty(cop.Owner))
{
Console.WriteLine($"券被抢了");
}
else
{
cop.Owner = _currOwner;
Thread.Sleep(5000);
ctx.SaveChanges();
Console.WriteLine($"恭喜{_currOwner}抢到券{cop.Id}了");
}
tx.Commit();
Console.ReadLine();

  解决:但这个是排他锁,有可能造成线程卡顿问题

    

  3.2 通过定义鉴权字段,乐观并发控制

    CouponConfig添加配置

            builder.Property(x => x.Owner).IsConcurrencyToken();

    抢券代码:

string _currOwner = Console.ReadLine();//当前用户
using var ctx = new MyDBContext();
var cop = ctx.Coupons.Single(x => x.Id == 2);
if (!string.IsNullOrEmpty(cop.Owner))
{
Console.WriteLine($"券被抢了");
}
else
{
Thread.Sleep(5000);
try
{
cop.Owner = _currOwner;
await ctx.SaveChangesAsync();
Console.WriteLine($"恭喜{_currOwner}抢到券{cop.Id}了");
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.First();
var dbValues = entry.GetDatabaseValues();
var newOwner = dbValues.GetValue<string>(nameof(Coupon.Owner));
Console.WriteLine($"并发冲突,{newOwner}已经抢到该券了");
}
}

    结果:

      

    根据update语句,可用看出where加了owner=旧值,来判断是否发生过更改

  3.3 添加数据版本标识

    如果无法定义一个明确的鉴权字段,那么可用通过新增一个字段,来标识数据来进行鉴权

    public class Coupon
{
public int Id { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public string? Owner { get; set; }
public byte[] RowVersion { get; set; } #迁移到数据库,类型为rowversion,当数据更新时,版本会自动递增
}

    迁移后数据库表代码

CREATE TABLE [dbo].[Coupons] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NOT NULL,
[Description] NVARCHAR (MAX) NULL,
[Owner] NVARCHAR (MAX) NULL,
[RowVersion] ROWVERSION NOT NULL,
CONSTRAINT [PK_Coupons] PRIMARY KEY CLUSTERED ([Id] ASC)
);

    CouponConfig添加配置

            builder.Property(x => x.RowVersion).IsRowVersion();

    抢券代码同3.2

    结果:

  

  理论和3.2相同,where会做一个rowversion的旧值判断

  总结:这三种方法由浅入深,各有利弊,在并发量不大的情况下使用3.1,并发量较大的情况下使用3.2&3.3

  感谢关注!!

  

EF Code 如何应对高并发的更多相关文章

  1. Memcached笔记——(四)应对高并发攻击【转】

    http://snowolf.iteye.com/blog/1677495 近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最 ...

  2. SpringCloud应对高并发的思路

    一.Eureka的高可用性 Eureka下面的服务实例默认每隔30秒会发送一个HTTP心跳给Eureka,来告诉Eureka服务还活着,每个服务实例每隔30秒也会通过HTTP请求向Eureka获取服务 ...

  3. 《即时消息技术剖析与实战》学习笔记10——IM系统如何应对高并发

    一.IM 系统的高并发场景 IM 系统中,高并发多见于直播互动场景.比如直播间,在直播过程中,观众会给主播打赏.送礼.发送弹幕等,尤其是明星直播间,几十万.上百万人的规模一点也不稀奇.近期随着武汉新型 ...

  4. Memcached笔记——(四)应对高并发攻击

    近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...

  5. 【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发

    对于一个互联网平台来说,高并发是经常会遇到的场景.最有代表性的比如秒杀和抢购.高并发会出现三个特点: 1.高并发读取 2.高并发写入(一致性) 3.出现超卖问题 前端如何应对? 1.缓存静态数据,例如 ...

  6. 基于tomcat为了应对高并发模型实现webserver

    在博客上,一个简单的AIOweb来样加工.查看AIO异步处理,依靠操作系统完成IO操作Proactor处理模型确实很强大,它可以实现高并发.高响应server一个很好的选择,但在tomcat中间con ...

  7. Linux下配置tomcat+apr+native应对高并发

    摘要:在慢速网络上Tomcat线程数开到300以上的水平,不配APR,基本上300个线程狠快就会用满,以后的请求就只好等待.但是配上APR之后,Tomcat将以JNI的形式调用Apache HTTP服 ...

  8. (转)Linux下配置tomcat+apr+native应对高并发

    摘要:在慢速网络上Tomcat线程数开到300以上的水平,不配APR,基本上300个线程狠快就会用满,以后的请求就只好等待.但是配上APR之后,Tomcat将以JNI的形式调用Apache HTTP服 ...

  9. Nginx优化配置,轻松应对高并发

    Nginx现在已经是最火的web服务器之一,尤其在静态分离和负载均衡方面,性能十分优越.接下来我们主要看下Nginx在高并发环境下的优化配置,主要是针对 nginx.conf 文件的属性设置.我们打开 ...

  10. php怎样应对高并发

    高并发下的数据安全 我们知道在多线程写入同一个文件的时候,会出现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的). 如果是M ...

随机推荐

  1. Spring的隔离级别,Spring事务传播属性,Spring事务与数据库事务之间的联系

    一.Spring五大事务隔离级别 Spring事务隔离级别比数据库事务隔离级别多一个default在进行配置的时候,如果数据库和spring代码中的隔离级别不同,那么以spring的配置为主.1) D ...

  2. noi 1.1 3 对齐输出

    描述 输入三个整数,按每个整数占8个字符的宽度,右对齐输出它们. 输入 只有一行,包含三个整数,整数之间以一个空格分开. 输出 只有一行,按照格式要求依次输出三个整数,之间以一个空格分开. 样例输入 ...

  3. el-table 固定列错位问题

    1. 问题描述:el-table使用固定列时,使用keep-alive后页面切换导致该列错位. 2. 解决方法:使用el-table的doLayout方法对表格进行重新布局 activated() { ...

  4. Vue.js + TypeScript 项目构建 (图形界面构建)

    一,打开图形界面 vue ui 二,创建文件       三,创建成功

  5. mysql的隔离级别以及存储引擎

    一.隔离级别 1.可序列化:(SERIALIZABLE):如果隔离级别为序列化,则用户之间通过一个接一个顺序地执行当前的事务,这种隔离级别提供了事务之间最大限度的隔离. 2.可重复读(REPEATAB ...

  6. create-react-app react 使用dll抽离公共库,大幅缩减项目体积,及项目打包速度

    1.安装依赖(clean-webpack-plugin.add-asset-html-webpack-plugin.webpack-cli) yarn add clean-webpack-plugin ...

  7. 转载一个很强大的GIT存储库学习链接

    https://learngitbranching.js.org/?locale=zh_CN 可以按照步骤一步步学习相关的知识点

  8. 【Win11】电脑开机内存占用过高

    联想拯救者 Y7000P 1.Win+R打开运行输入"MdSched"   重启 2.Windows PowerShell(管理员)->并运行该命令 Disable-MMAg ...

  9. Redis5.0.4-集群(单机版)搭建

    最近尝试搭建了一下redis集群,这里记录一下,最后附上的是参考的博客地址. 安装C语言编译环境GCC yum install -y gcc-c++ 下载redis并编译安装 下载: wget htt ...

  10. Linux env commands

    1.新机新增root 密码 sudo passwd root 2.新增用户密码 sudo passwd YOUR_USER_NAME NEW PW: NEW PW: 3.SSH Server sudo ...