大话程序猿眼里的高并发
简单理解下高并发:
高并发是指在同一个时间点,有很多用户同时的访问URL地址,比如:淘宝的双11,双12,就会产生高并发,如贴吧的爆吧,就是恶意的高并发请求,也就是
DDOS攻击,
再屌丝点的说法就像玩撸啊撸被ADC暴击了一样,那伤害你懂得(如果你看懂了,这个说法说明是正在奔向人生巅峰的
屌丝)。
高并发会来带的后果:
服务端:导致站点服务器/DB服务器资源被占满崩溃,可能产生不是理想中的重复杂乱的数据。
用户角度:尼玛,这么卡,老子来参加活动的,刷新了还是这样,垃圾网站,再也不来了。
我的经历:
在做公司产品网站的过程中,经常会有这样的需求,比如什么搞个活动专题,抽奖,签到,搞个积分竞拍 等等,如果没有考虑到高并发下的
数据处理,那就Game Over了,很容易导致抽奖被多抽走,签到会
发现一个用户有多条记录,签到一次获得了获得了多积分,等等,各种超出正常逻辑的现象,这就是做产品网站必须考虑的问题,因为这些都是面向大量用户的,而不是像做ERP管理系统,OA系统那样,只是面向员工。
下面我进行
实例分析,简单粗暴,动态分析,纯属本人个人经验分享,
如有说错,或者有更好的建议或者意见的请留言,大家一起成长。
1,高并发的数据处理:
通过表设计或者SQL语句来防止包并发下的数据错乱问题
通过程序代码防止包并发下的数据错乱问题
-------------------------------------------[我只是
美丽的分割线]-------------------------------------------
如例子1(通过表设计防止并发导致数据错乱)
需求点:
【签到功能】
一天一个用户只能签到一次,
签到成功后用户获取到一个积分
已知表:
用户表,包含积分字段
高并发意淫分析(属于开发前的猜测):
在高并发的情况下,会导致,一个用户签到记录会有多条,后者用户签到后不止加一个积分。
我的设计:
首先更具需求我会添加一张签到记录表,
重点来了,这张表需要把用户唯一标识字段(ID,Token)和签到日期字段添加为
唯一约束,或者唯一索引,这样就可以 防止并发的时候插入重复用户的签到记录。
然后再程序代码逻辑里,先执行签到数据的添加,添加成功后再进行积分的添加,这样就可以防止重复的添加积分了。
最后我还是建议所有的数据操作都写在一个sql事务里面, 这样在添加失败,或者编辑用户积分失败的时候可以回滚数据。
-------------------------------------------[我只是美丽的分割线]-------------------------------------------
如例子2(事务+通过更新锁 防止并发导致数据错乱 或者事物+Update的锁表机制)
需求点:
【抽奖功能】
抽奖一次消耗一个积分
抽奖中奖后编辑剩余奖品总数
剩余奖品总数为0,或者用户积分为0的时候无法进行抽奖
已知表 :
用户表,包含积分字段
奖品表,包含奖品剩余数量字段
高并发意淫分析(属于开发前的猜测):
在高并发的情况下,会导致用户参与抽奖的时候积分被扣除,而奖品实际上已经被抽完了
我的设计:
在事物里,通过WITH (UPDLOCK) 锁住商品表,或者Update 表的编辑时间字段,来把数据行锁住,然后进行商品数量的消耗,和用户积分的消耗,都完成后提交事物,失败就回滚。
这样就可以保证,只有可能存在一个操作在操作这件商品的数量,只有等到这个操作事物提交后,其他的操作这个商品行的事物才会继续执行。
-------------------------------------------[我只是美丽的分割线]-------------------------------------------
如例子3(通过程序代码防止包并发下的数据错乱问题)
需求点:
【缓存数据到cache里】,
当缓存不存在的时候,从数据库中获取并保存在cache里,如果存在从cache里获取,每天10点必须更新一次,其他时间点缓存两个小时更新一次
到10点的时候,凡是打开页面的用户会自动刷新页面
问题点:
这里有个逻辑用户触发缓存的更新,用户刷新页面,当缓存存在的时候,会取到最后一次缓存更新时间,如果当前时间大于十点,并且最后缓存时间是10点前,则会从数据库中重新获取数据保存到cache中。
还有客户端页面会在10点时候用js发起页面的刷新,就是因为有这样的逻辑,导致10点的时候有很多并发请求同时过来,然后就会导致很多的sql查询操作,理想的逻辑是,只有一个请求会去数据库获取,其他都是从缓存中获取数据。(因为这个sql查询很耗服务器性能,所以导致在10点的时候,突然间
数据库服务器压力暴增)
解决问题:
C#通过 (锁)lock,在从数据读取到缓存的那段代码前面加上锁,这样在并发的情况下只会有一个请求是从数据库里获取数据,其他都是从缓存中获取。
-------------------------------------------[我只是美丽的分割线]-------------------------------------------
2,高并发的下的服务器压力均衡,合理站点架设,DB部署
以下我所知道的:
1,服务器代理nginx,做服务器的均衡负载,把压力均衡到多台服务器
2,部署redis服务器,或者mongodb服务器,把一些常用的查询数据,并且不会经常的变化的数据保存到其他nosql DB服务器中,来减少数据库服务器的压力,加快数据的响应速度。
3,前端
JS脚本合理控制请求,如,防止用户重复点击导致的ajax多余的请求,等等。
4,在高并发
接口的设计中可以使用具有高并发能力的
编程语言去开发,如:nodejs 做web接口
3,并发测试神器推荐:
Apache JMeter
Microsoft Web Application Stress Tool
(如果还有更好的工具求推荐,简单易用)