电商实例、业务并发、网站并发及解决方法
一、怎么防止多用户同一时间抢购同一商品,防止高并发同时下单同一商品?
http://ask.csdn.net/questions/159351
http://www.cnblogs.com/lingmaozhijia/articles/1339222.html
最近在做抢购系统,但头疼的是,在多用户高并发的情况下经常会库存出现问题。排查到,在同一时间内多用户同时下单导致查询和插入不同步了,而查询中跟插入又有时间差而在高并发的情况下导致库存问题(我的项目大概是这样,首先 for update查出商品信息表,放入全局表里数组里,当用户扣款余额成功后,update商品信息表减去该用户下单的数量。数据库用的mysql,查询商品信息表的时候是加锁过的,但商品信息表数据越来越多的时候查询有时间差,导致高并发的时候在查询商品信息表放进变量数组里的时候,在执行后面的时间差里,其他用户也在下单,导致库存有问题)。现在提问,同一时间内同一个商品防止多用户抢购,也就是说同一秒内在高并发的情况下只能被一个用户下单,目前的思路是排队,阻塞队列。
1、update table set num=num-1 where num>1
不查直接更新,更新成功代表抢到了
2、把抢购系统放成两步,第一步为下单(即抢购),下单成功立即减少数量,更新表数据,
第二部为付款,后台写个程序,如果半个小时不付款,自动删除订单,然后增加数量。
这样的话,可以避过并发了,如果一步走,时间再短也会有并发的问题。
3、数据库中可以加行锁
4、好像有点像我买飞机票
下单立即就减数量,半小时不付款则取消订单 数量恢复。
5、可以使用队列+锁表来做。
二、最近一公司在为我单位在B/S平台上做生产调度管理,平台是MySQL4.0+Java。在测试过程中我发现开发人员没有对数据的并发进行控制。即两个人同时修改一条记录时,两个人均可提交,且最后提交人的数据会复盖前面修改人的记录。
本人对此提出异议后,软件开发人员告之,用生产管理系统中的权限管理,就可解决并发控制的问题!!!
我认为由于B/S结构不能象C/S结构那样始终与数据库相连,所以数据库本身进行并发控制的能力就被削弱了,故在提交前需要前台程序进行相应判断。而使用任何权限来限制用户的写操作(对同一条记录),从根本上是无法避免并发产生的!
1、如果把程序中的SQL语句,也就是UPDATE改一下应该就可以了吧!UPDATE加上WHERE条件,不光是主键相等,而且更新的字段,也必须加上原始的值.如表结构为:
ID,aNAME,age
数据
100,anders,40
101,arg,56
如果要把arg的name改为args的话
update 表名 set aname = 'args' where ID = 101 and aname = 'arg'
这样的话如果人先把aname改为其它的,更新就是报错!不会出现楼主所说的情况。
三、网站并发
时常看到高并发的问题,但高并发其实是最不需要考虑的东西。为何,他虚无缥缈,很少有网站真的需要这些东西,而且其中很多技术,其实你已经在用了。有这个意识就够了,不需要时刻盯着这个问题。只很少的网站真的能达到高并发。
简单做一个归纳,从低成本、高性能和高扩张性的角度来说有如下处理方案:
1、HTML静态化
2、图片服务器分离
3、数据库集群和库表散列
4、缓存
5、镜像
6、负载均衡;一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。
下面也是一个牛人所做的总结,跟上面部分相同。 高并发时,性能瓶颈及当前常用的应对措施
1.数据库瓶颈。Mysql并发链接100
2.apache 并发链接1500
3.程序执行效率
1.有数据库瓶颈时,当前处理方案无外乎 主从,集群。增加memcached【内存对象缓存系统】
如:手机之家新系统介绍及架构分享(http://www.slideshare.net/Fenng/ss-1218991?from=ss_embed)
就是在cache【缓存】层做优化 。又拍网架构(http://www.bopor.com/?p=652) 是以增加数据库,分表分库的方法解决。 Sina增加了mq(消息队列)来分发数据。 还风站用了key-value的数据库。其实这可以理解成一个持久化的缓存。
2.apache瓶颈。
增加服务器。负载均衡。如sina的F5
由于进程数的限制。会把一些基本不变的代码挪出来放到单独的服务器。如css/js/图片。
国内成功的案例是tom的cdn。又如nginx的横空出世和squid的反向代理都是基于这个原因出来的。
3.php的执行效率。原因有多个。
1).本身的效率低。
解决的成功案例是Zend Optimizer 和 facebooke的hiphop。Taobao是把php代码编译成模块解决效率问题。
2). 数据库查询效率问题。如可能有order by ,group by 等Sql数据问题。
这个其实应该归结到数据库设计问题。
解决的办法是建立正确的索引。增加memcache【分布式的高速缓存系统】。
对like表 用专用的sphinx.【SQL的全文检索引擎】和lucence 【基于Java 的全文信息检索】等搜索服务。
程序员都应该会用explain对sql语句作分析。
四、Web系统大规模并发—电商秒杀与抢购
http://www.csdn.net/article/2014-11-28/2822858
2. 悲观锁思路
解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。
悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。
虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。
3. FIFO队列思路
那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。
然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。
4. 乐观锁思路
这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。
有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。
1)、乐观锁存在的问题,例: 两个请求(A、B)同时都会更新一条记录, A更新(判断版本通过)这时A事务还没结束(后面还有逻辑), 此时,B也更新(判断版本也通过)B事务结束, 后面A结束,这样A事务的更新不就错了吗(脏读) 。(乐观锁本来就不能解决脏读的问题)