高并发,高可用系统的一些思考

高并发,高可用系统的一些思考

author: he xiaodong date: 2019-04-11

个人理解高并发系统主要在于:机器资源的合理分配和性能的压榨,代码质量,及维护高并发系统在请求峰值的时候,系统中有机器宕机时整个系统的可用性。核心是提高吞吐,降低响应时间。

随意想

还有几个观点是:高并发技术可以有,但是很多公司没有高并发场景。越是没有高并发场景的公司越愿意问高并发的问题,是为了考察面试者对于行业尖端技能的学习还是为了压价?而有高并发场景的公司一般很在乎基础,基础好的人写出来的代码比烂代码性能强一点的话,并发时会严重放大提升的这一点性能。

至于在有并发场景之前的优化网站性能,多数情况会依赖:1. 前端资源 CDN 化,公用的资源编译压缩,同时使用浏览器自身缓存,提升资源加载速度,也减少访问一个页面给此域名带来很多的请求。 2. 优化 SQL 操作,95%+ 的问题是 sql 优化可以提升的,对应也有代码中的魔性操作,带来的执行效率的问题。

高并发依赖于场景和逻辑

不一定每个场景都会产生高并发,不要为了高并发而盲目的设计,过度设计带来的问题远比意料之外的高并发要多很多,依赖于具体场景和行为进行分析,一个购物类网站,抢购场景,会触发很多的读取商品详情,计算库存等操作,而且不需要每个请求都到达支付页面,也不会在网站主页带来很多的请求,所以需要针对抢购场景进行优化,而不是巨大的支付流程进行优化,当然商品数量多和用户多的情况,才需要也优化一下支付流程。

抛开场景,不谈流量的盲目高并发设计,一般是过度设计,未来维护臃肿而复杂的代码会惩罚你当初的过度设计。

突如其来的高并发

基本是被人刷了,或者比预估的情况要多了几倍,才有这种情况,前者可能性很大,最近这两年的金融网站,区块链,xx币网站,基本会被羊毛党盯上,没做好访问防作弊,或者被对手 ddos 攻击,都会造成高并发中网站瘫痪,清洗流量一般就可以的,不要让辣鸡流量贯穿整个业务。高并发会带来网站请求慢,但网站请求慢不一定是高并发了,对症下药。

如果是网红带货什么的,给网站带来高并发了,这种情况下可以在提前流量上做些手脚,例如:1. 用消息队列排队流量,例如猴王网站的抢购 2. 采用一些高端点的验证码,让一些秒杀抢购的机器号被过滤出去,尽量不影响真实用户的抢购结果 3. 分层过滤,例如静态资源放在 CDN 上,NGINX 层面使用自身的缓存,根据路由缓存基础数据,其他动态数据再读写数据库,而不是每个请求都经过整体的业务,这样带来的压力太大了,而且也不值得。

并发中的整体项目稳定性

可以将高并发的业务部分分离到单独的服务器。这种情况下能够避免这部分业务带来机器性能的消耗,从而影响整个项目的稳定性,这样的结果不太好的。也可以预先将热数据放到缓存中,提高读写效率,也能让 MySQL 比较稳定,一般情况下能有高并发的网站,数据量也不少,举例某个电商网站,可能有 100w 商品数据,但大家抢购的是今天热推的 10 个商品,将这十个数据提取放到缓存中,而不是每次去数据库中查询,当然 MySQL 设置合理的话,自身的 buffer pool 也能搞定这些热数据缓存。这样相当于将这 10 条数据隔离出来,而不是影响到整体数据。关于热点数据的发现,还有一些高端的是从 NGINX 访问日志层面实时分析,据说淘宝这种是这样的,实时发现访问很多的路由,分析路由获取到对应的商品数据,放到缓存中,减轻服务器压力。

稳定性不光存在于业务机器层面,也可能是网络宽带不够,或者程序在磁盘写日志的时候遇到瓶颈,或者内存不够,导致可用缓存空间很小。这些在测试和计算层面需要注意的问题,也会影响整体稳定性和性能的,应该提前解决。例如秒杀系统需要关注 CPU,并发读需要关注缓存,静态资源多的也需要考虑宽带。

预先测试

简单可以是压测关键业务部分,简单的查询一般不会带来问题,这个页面的静态资源太多,同时都在统一个域名下的话,相当于在现有并发的数量上加了更多,这非常不利,对于浏览器的加载也是不利的,简单业务也会体验很差。压力测试应当遵循慢慢提升流量的方式,并发量和响应时间并不是等比例上涨的,慢慢提升并发量的测试,会展示代码的瓶颈部分在哪,然后在去解决和提升。测试也可以

在基础的并发测试之外,还有在正是服务器上的全链路压力测试,为了防止和真实数据冲突,可以将请求中加上额外的标记,或者针对特定的用户帐号测试,在数据中体现这部分额外标记,测试完毕之后将数据删除。

同时,不要高并发的主要业务一直占用机器的 100% 的运算能力,这样整体逻辑和请求支持已经到了极限,基本再高一点就会造成问题,应该尽量让业务只占用机器 60-70% 的运算能力,留出一部分的余地,防止意外。

安全及备用方案
  1. 从 NGINX 层面限制单个 IP 单位时间内请求频率和次数,屏蔽掉机器刷的可能性,从而不影响正常访问。 2. 切记高并发 + 高可用不可以用单点系统,例如不能因为热数据少而就用一台 Redis 服务器,或者更狠的直接本机缓存,一旦系统崩溃,相当于触发连锁反应,连保存现场和恢复都很难。 3. 提前设计兜底方案 ① 降级,例如商品详情页面不展示推荐商品,或者减少推荐商品展示数量等, ② 限流,不让更多流量涌入,能减少很多压力 ③ 过载临界点拒绝服务,这个是最坏的情况,直接阻断压垮系统的最后一个流量。

参考链接:

  1. 构建一个高性能、高可用的大型分布式网站
  2. 关于高并发 - 知乎专栏
  3. 如何获得高并发经验 - 知乎问答
  4. sf 我们讨论高并发的时候在讨论什么
  5. 极客时间 - 设计一个高并发系统 -> 用我的码去购买