阿里阿里P8架构师谈:高并发架构解决方案总结架构师谈:高并发架构解决方案总结
一、关于高并发
高并发是指在同一个时间点,有很多用户同时访问URL地址,比如:淘宝的双11、双12,就会产生高并发。又如贴吧的爆
吧,就是恶意的高并发请求,也就是DDOS攻击。
1 高并发会来带的后果
服务端:导致站点服务器/DB服务器资源被占满崩溃,数据的存储和更新结果和理想的设计是不一样的,比如:出现重复的数
据记录,多次添加了用户积分等。
用户角度:网站打不开
服务器雪崩:
2 并发下的数据处理
通过表设计,如:记录表添加唯一约束,数据处理逻辑使用事物防止并发下的数据错乱问题。通过服务端锁进程防止包并发下
的数据错乱问题。
这里主要讲述的是在并发请求下的数据逻辑处理的接口,如何保证数据的一致性和完整性,这里的并发可能是大量用户发起
的,也可能攻击者通过并发工具发起的并发请求。
例子1:通过表设计防止并发导致数据错乱
需求点:
【签到功能】一天一个用户只能签到一次,签到成功后用户获取到一个积分。
已知表:
1、用户表,包含积分字段;
2、高并发意淫分析(属于开发前的猜测): 在高并发的情况下,会导致一个用户签到记录会有多条,或者用户签到后不止加一
积分。
我的设计:首先根据需求我会添加一张签到记录表,重点来了,这张表需要把用户唯一标识字段(ID,Token)和签到日期字段添
加为唯一约束,或者唯一索引,这样就可以防止并发的时候插入重复用户的签到记录。然后再程序代码逻辑里,先执行签到数
据的添加(这里可以防止并发,添加成功后再进行积分的添加,这样就可以防止重复地添加积分了。最后我还是建议所有的数
据操作都写在一个sql事务里面, 这样在添加失败,或者编辑用户积分失败的时候可以回滚数据。
例子2:事务+通过更新锁,防止并发导致数据错乱;或者事物+Update的锁表机制
需求点:【抽奖功能】抽奖一次消耗一个积分,抽奖中奖后编辑剩余奖品总数,剩余奖品总数为0,或者用户积分为0的时候
无法进行抽奖。
已知表:用户表,包含积分字段 奖品表,包含奖品剩余数量字段。
高并发意淫分析(属于开发前的猜测):在高并发的情况下,会导致用户参与抽奖的时候积分被扣除,而奖品实际上已经被抽完
了。
我的设计:在事物里,通过WITH(UPDLOCK)锁住商品表,或者Update 表的奖品剩余数量和最后编辑时间字段,来把数据行
锁住,然后进行用户积分的消耗,都完成后提交事物,失败就回滚。 这样就可以保证,只有可能存在一个操作在操作这件商
品的数量,只有等到这个操作事物提交后,其他的操作这个商品行的事物才会继续执行。
例子3:通过程序代码防止包并发下的数据错乱问题
需求点:【缓存数据到cache里】,当缓存不存在的时候,从数据库中获取并保存在cache里,如果存在从cache里获取,每
天10点必须更新一次,其他时间点缓存两个小时更新一次 到10点的时候,凡是打开页面的用户会自动刷新页面。
问题点:这里有个逻辑用户触发缓存的更新,用户刷新页面,当缓存存在的时候,会取到最后一次缓存更新时间,如果当前时
间大于十点,并且最后缓存时间是10点前,则会从数据库中重新获取数据保存到cache中。 还有客户端页面会在10点时候用js
发起页面的刷新,就是因为有这样的逻辑,导致10点的时候有很多并发请求同时过来,然后就会导致很多的sql查询操作,理
想的逻辑是,只有一个请求会去数据库获取,其他都是从缓存中获取数据。(因为这个sql查询很耗服务器性能,所以导致在10
点的时候,突然间数据库服务器压力暴增)
解决问题:通过(锁)lock,在从数据读取到缓存的那段代码前面加上锁,这样在并发的情况下只会有一个请求是从数据库里
获取数据,其他都是从缓存中获取。
3 访问量大的数据统计接口