根据实际工作经验总结一下个人.Net高并发处理做法

场景描述

1.用户下单,商品库存已经不足了,但还是扣减了

2.医生开方,药品不足了,但还是被开了出去

··· 类似场景

解决思路

思路1:预扣库存

用户下单时,系统先进行预扣库存操作,然后后将“下单业务”发布到MQ(消息队列)进行处理,成功通知,失败回滚预扣库存操作

  • 对于预扣库存时可能出现的“超卖”现象,可以采用针对数据库表的悲观/乐观锁,具体用哪种,看场景,下文有讲

思路2:异步通知

用户下单时,直接提交,后台丢入MQ,然后进行业务处理,前端直接提示操作完成

  • 这个处理方式,极大的提升吞吐量,因为不需要“即刻”处理,后续获取结果方式则可通过各种方式来通知,如微信公众的消息订阅模板消息,短信、邮件,等。
  • 这个场景在BAT产品中可以找到相关例子,例如早期微信充值手机花费的早期处理思路,就是提示“充值操作完成,具体结果稍后通知” (现在已经改了,页面等待即会通知)

悲观/乐观锁 使用场景

基本概念

悲观

阻塞(等待),超时报错

  • 假设会冲突,好处是能保持数据一致性,设计思想是不管咋样先无脑上锁
    ,说人话就是“我每次出门都先带一瓶防狼喷雾,不管我会不会遇到危险情况,我假设可能我被坏蛋盯上了”显而易见,这样我出门花费的时间成本肯定增加了,代码层面就是耗费的性能增加了

乐观

假设不冲突,提交更新对比版本号,失败报错,设计思想就是是尽量减少锁的使用

  • 说人话就是“出门不带防狼喷雾了,我觉得世界坏蛋不多

  • 高并发的修改操作,乐观会频繁更新冲突报错,如果你逻辑写了重试操作,那么久一直报错重试N循环,这时候已经不适用乐观,应该使用悲观

结合场景

  • 用户下单,医生开方,规模到达一定量时,肯定要保证不要出现“超卖”现象,因此扣减库存使用悲观无可厚非
  • 其他场景,如基础字典数据维护,用户修改个人信息,扣减用户余额等一系列操作,一般稳妥期间都会加上乐观锁,其场景就是并发量并不大

实际代码应用

这种锁机制,不管你用什么基本都很成熟了

针对数据库,我这里推荐的sqlsugar这个ORM,使用sqlsugar能够很容易的针对数据库表进行乐观/悲观锁的操作,其稳定和成熟性也经过了多年多家大头公司认可了,使用方法看官方文档很详细

如果是分布式锁,这里推荐的是FreeRedis它里面有基于redis封装好了分布式锁的使用,调用十分简便,我个人实际公司业务上也是使用了这个

为了解决A问题而带来的B问题解决方案

引子:

通过上诉解决方案后,理论上技术层面性能问题顶住没啥问题了

(这如果还有问题,想必你司业务及其牛X,更进阶的方案也没啥实际上的技术思路提升,无非就是把处理业务的模块继续拆分,拆分后的各个粒度更小的业务服务再加大规模的集群,也就是现在大厂普遍的微服务)

但是可能会有一个新的问题,例如:A客户看中一个热门商品满心期待的去下单,下单完心里美滋滋幻想着用上这个商品然后去睡觉,第二天起来才看到 “对不起,下单失败,库存不足”,直接各种恶毒的语言开始诅咒开发这个产品的人

某些业务场景下这种情况是允许的,而在某些产品上,这种情况则是不被允许存在的,实际解决其实也简单,如果项目有ws,可以考虑在页面等待ws获取结果,如果没有则轮询请求某个api返回最终结果

有没有发现,我本来 “普通一个接口搞定的事情,现在为了解决‘可能存在的’问题要做的事情反而多了”所以具体公司业务开发的时候,更多的是要掌握好实际需求以及实际预估场景,一句话自己根据实际场景把握好,“编程永远没有万金油”

这就是现如今利用各类技术解决问题后,衍生出来的新问题,因此请实实在在的确保你的项目实际上存在这么大的流量和高并发,真真切切存在此类问题需要解决,才考虑这些技术手段的解决方案,千万不要成为段子中的:“技术上异步填谷削锋,运行时用户白天20晚上15” 我经常提醒自己,“不要为了写代码而写代码”

以上就是我对类似的处理的宏观处理思想以及关键点位的实际处理方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章