http://www.notedeep.com/note/38/page/529
【扩容】【静态化】【限流】 A:扩容 加机器,这是最简单的方法。 B:静态化 将活动页面上的所有可以静态的元素全部静态化,并且通过CDN加速 C:限流 一般都会采用IP级别的限流,即针对某一个IP,限制单位时间内发起请求数量。后端的数据库在高并发和超卖下会遇到什么问题呢?主要会有如下3个问题:(主要讨论写的问题,读的问题通过增加cache可以很容易的解决) I: 一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。 II: 其次,超卖的根结在于减库存操作是一个事务操作 III:最后,当减库存和高并发碰到一起的时候,由于操作的库存数目在同一行,就会出现争抢InnoDB行锁的问题,导致出现互相等待甚至死锁,从而大大降低MySQL的处理性能。错误的方法:
select count from s_store where postID = 12345;
update s_store set count = count - 1 where postID = 12345;
insert into buy_log (userID, postID) VALUES (22, 12345);
count 可能会变为 -1
可能会插入多条购买的记录
affect_rows = update s_store set count = count - 1 where count>=1 and postID = 12345;
insert into buy_log (userID, postID) VALUES (22, 12345);
count = select count from s_store where postID = 12345;
affect_rows = update s_store set count = count - 1 where count=count and postID = 12345;
insert into buy_log (userID, postID) VALUES (22, 12345);
select … for update.事务给rows上排他锁,其他事务必须排队等待。相当于在数据库层面串行化了。显而易见的是随着并发量的增大,事务处理的性能越差。
count = SELECT count FROM s_store WHERE postID = 12345 AND count>0 FOR UPDATE;
affect_rows = UPDATE s_store SET count=count-1 WHERE postID = 12345 AND count> 0;
insert into buy_log (userID, postID) VALUES (22, 12345);
优化悲观锁的方法:核心是各个层面做好排队即可,如:
通过innodb_thread_concurrency参数来控制InnoDB存储引擎层的并发量。将innodb_thread_concurrency设置为16,性能的确会有一定的提升。并发线程数在128的时候,TPS从原有的4300提升为了7200,将近有65%的性能提升。但是在256线程之后,性能依旧堪忧。
性能又获得了进一步的提升。但是线程池这里有个参数thread_pool_oversubscribe,这个参数其实有点类似云计算中“超售”概念,即MySQL的线程池允许有额外的线程运行。该参数默认是3,之前thread_pool_size设置为16,那么总共允许16*(1+3)=64个线程同时运行。这个参数的默认值本身没有问题,但是对于秒杀应用来说确是不需要的,因为之前已经讨论过,秒杀应用是串行的。所以将参数thread_pool_oversubscribe设置为1,秒杀还能有进一步的提升。