谈谈并发

谈谈【非】高并发

开篇

大部分程序员都没有机会到互联网公司中接触高并发,即使身在互联网公司中,也不一定能够亲自操刀高并发代码,但是如果真的让你攻坚一个高并发业务的时候,稍有不慎就会造成严重的并发问题。所以,高并发成了爬上技术金字塔尖的拦路猛虎之一。

关于高并发,我将用整个程序员生涯来不断体会理解与分享。
今天这篇文章,讲讲初中级程序员在CURD打怪升级初期,怎么去理解【并发】,为将来的【高并发】打下扎实基础。

问题由来

并发问题,抽象起来就是:资源竞争。虽然短短四个字,但这其中要讲起来,可以开个专栏。在面向Spring编程中(Java程序员已经跳不出这个圈子了),贫血模型发挥到了极致,各种O(VO,DTO等)加上三层(Controller,Service,Dao)是大部分初中级程序员的上班工作对象。在这个环境下,暂且把这些O理解为资源。而每一次的http请求,就是竞争。

具体问题具体分析

1. 非严肃的独有的资源竞争

非严肃的,即状态的改变不依赖上一个状态,直接覆盖,并不会造成错误。比如修改用户昵称,不管你以前叫张三还是李四,都可以直接设置为奥观海或者川建国;用户独享的资源,一般不会出现并发,即使出现并发,也允许直接覆盖。典型的场景就是用户修改自己的信息。资源只会被用户自己操作,一般情况下,不会出现并发。即使用户真的在多个页面同时提交修改,那么我们可以认为,任何一次提交都可以直接覆盖前面的提交。

2. 非严肃的共享的资源竞争

比如多个管理员都在编辑商品信息,比如多个会员同时编辑文档。这类型业务,可做并发控制,也可以不做。要不要做,可以从用户体验上来权衡。

实际上,CRM,OA等项目中大部分都是这种情况,如果要做并发控制的话,可以通过版本号来解决。

3. 严肃的共享的资源竞争

严肃的,即状态的改变依赖上一个状态,比如计数器的+1操作,需要知道当前计数,才能计算出下一个计数;再比如充值100元,得知道当前余额,才能够计算出充值之后的余额。再再比如商品的库存,当你去减库存的时候,得知道当前的库存是多少,才能够计算出新的库存是多少。这些情况下,需要控制并发。这类严肃资源一旦出现并发问题,那么后果很严重。

严肃的共享资源竞争问题,可以这么解决:

  1. 使用Java的锁(Synchronize,Lock):
//伪代码
lock.lock();

balance = queryDB();
updateDBWithNewBalance(balance - money);

lock.unlock();

基本思想是将1)读取当前状态、2)状态改变、3)新状态持久化这三个步骤同步执行。
这种方案的缺点是无法在集群中使用。当然如果把锁换成分布式锁,就不存在集群扩容的问题了。

  1. 利用数据库的行级锁:
update set balance = balance - money where userId = ? and balance > money;

注:程序要判断修改的影响行数是不是1。

保证余额不能少于0。这个方案在【非】高并发的情况,简单耐用,实在居家旅行增删改必备技能。

多想一点

上面所讲的,在【非】高并发的情况,已经可以交差上生产了,但是如果是高并发的情况呢?比如秒杀场景,红包场景等高并发场景,如果让流量洪峰瞬间流向数据库,那么你第二天就可以领盒饭了:)

我们需要其他手段来解决流量洪峰,比如削峰填谷的消息中间件。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值