讨论一下秒杀系统的技术难点与解决方案

 

前言

小伙伴们,我们先回顾一下,在一个系统中引入消息中间件后会给系统带来什么好处呢?

通过之前的文章我们了解到,引入MQ后主要可以解决三个问题:异步、解耦、削峰,小伙伴们可以回顾一下这篇文章什么是消息中间件?主要作用是什么?

今天王子就和大家聊一聊削峰的具体场景,针对一个电商系统中,秒杀系统这部分的技术难点与解决方案。

 

系统面临的瓶颈是什么

我们先了解一下,秒杀系统中具体有什么问题需要解决呢?王子给大家画一张图:

 

 

假如我们的系统有了秒杀的业务,那么会有海量的用户访问我们的订单系统集群,其实这里还不是技术的瓶颈,只要扩展订单系统集群,增加订单系统的机器数量就可以抗下这样甚至更高的高并发情况。

 

那么技术瓶颈是什么呢?

我们再来看数据库部分,你会发现无论你的订单系统集群增加多少机器,它们访问的还是一个数据库。那么每次面对秒杀系统这样的活动时,数据库要承受的压力是极大的,很可能因此宕机,导致整个系统崩掉,后果是很可怕的。

由此我们分析出,数据库是秒杀系统面临的一大瓶颈。

 

如何解决秒杀系统的瓶颈

刚才我们谈到,秒杀系统面临的技术瓶颈是数据库,那么我们如何解决呢?是不是要部署更多的数据库服务器,对数据库进行分库分表,然后让更多的数据库服务器共同抗下高并发的情况呢?

这种分库分表的策略是这样的,假设我们目前操作的是一个库中的一张订单表,那么分库后就变成了多个库,每个库里都只存一部分的订单数据,分库策略可以是按时间戳或者哈希算法计算得出(这不是本篇重点,以后会有单独的数据库专题讨论),分表呢就是可以在一个库里对订单表再次拆分成多张表,数据再次分片存储。

这种模式有什么好处呢?

好处其实是显而易见的,我们的高并发请求可以平均分配到多台数据库上,整个的数据库集群可以共同承担高并发带来的压力,而且也可以通过扩展数据库集群实现可以承担更高并发的能力。

说到这里,小伙伴们是不是觉得,这个问题就这么解决了呢?

王子可以明确的告诉大家,这种解决方法是很不靠谱的,除非公司的技术能力太弱,没有人能搭建出更可靠的架构才会选择这种下下策,通过堆叠机器数量来抵抗高并发下的压力。

试着想一下,假如我们的系统很受客户欢迎,用户量日渐增长,达到了海量的用户数,难道我们要不停的增加服务器数量吗?

服务器的成本是不是有点偏高了呢?

所以要解决这个问题,我们的出发点一定要正确,就是不能通过不停的增加机器解决这种问题,而是在有限的资源下设计出更优雅的架构来解决,这样的方法才是上策。

 

前台页面的优化

知道了我们应该在有限资源下进行架构优化,那么我们先思考一个问题。

用户参加秒杀活动的时候,是如何操作系统的呢?

就拿双十一抢购来说,在00:00的时候就是秒杀的时候,那么很多用户会提前几分钟把手机打开到对应的页面,没到时间就开始不停的刷新页面,等待秒杀开始那一刻的到来。

那么小伙伴们有没有考虑过,这些要刷新的页面都是从哪里来的呢?

我们的页面其实也是要有自己专门的订单页面服务器的,主要用于提供前端的访问页面,基本结构如下图:

 

所以,首先接受高并发请求的系统是前端页面系统。

大家思考一个问题,如果平时不是秒杀的时候,用户看的商品可能都是不同的,但是一旦有秒杀活动,可能有大量的用户一起不停的刷新同一个商品的同一个页面,对系统造成压力。

那么对于这个问题,我们应该怎么解决呢?

王子今天介绍的解决方案就是页面数据的静态化+多级缓存的策略。

 

页面数据静态化

我们先来聊一聊什么是页面数据的动态化。

假设我们的前端页面是动态化的,那么用户每次访问页面,都会向页面系统发送请求获取数据,然后前端页面根据获取的数据渲染页面,一般来说系统的演进都是从这种动态化开始的,比如jsp页面。

那么如何实现页面的静态化呢,其实就是改变页面获取数据的方式,每次获取数据不再是通过页面系统查询数据库而是从别的地方获取数据,避免每次都去访问后端数据库,对系统造成压力。

 

多级缓存

了解的静态化的思想,那么我们再来看看多级缓存是什么,我们要聊的多级缓存指的是CDN+Nginx+Redis的多级缓存架构。

什么意思呢?就是说页面的数据首先放一份到离用户最近的CDN上边。

可能有的小伙伴不理解CDN,王子给大家简单扫一下盲。

比如我们的系统服务器部署在北京,访问我们系统的用户在海南,那么它每次访问我们系统是要到我们北京的服务器上面获取数据吗?

不是的,我们是可以把静态化的页面数据部署到海南的CDN上边去的,而海南的用户就可以通过CDN获取到我们系统的页面数据。

这个CDN都是各种云厂商提供的服务,它就是我们架构中的第一级缓存

如果由于CDN中缓存过期等原因,导致没有从CDN中得到页面数据,那么此时用户就会将这个请求发送到我们北京的服务器上边,但是这个时候系统不是直接查询数据库返回数据的,而是先访问Nginx服务器上的缓存。

Nginx是可以基于Lua脚本实现本地缓存的,我们可以提前吧页面数据放到Nginx缓存中,作为第二级的缓存

如果Nginx上边也没有想要的数据呢?

那么此时可以通过Nginx上的lua脚本发送请求到Redis集群中加载数据,Redis集群就作为我们多级缓存架构的第三级缓存

如果在Redis集群中还是没有找到数据,我们再去从数据库加载出来,并更新到缓存里。

通过这样一套多级缓存的架构,我们就可以实现页面的静态化数据的存储(数据可能就是一段json串),这样对于我们的页面服务器本身压力就非常的小了。

架构图如下:

 

 

总结

今天我们聊了聊高并发系统下,堆积机器方案的弊端,同时也介绍了秒杀场景下面临的一些技术挑战。

又讲解了使用多级缓存架构构建静态化页面的方式。

但秒杀系统是一个复杂的系统,深入研究细节是很多的,王子主要是在这里介绍一下秒杀系统的整体场景,和针对于秒杀系统做的一些架构优化的思路,从而引出如何将RocketMQ落实到秒杀系统中,实现流量的削峰功效。

那么下篇文章我们就一起聊聊如何将MQ引入到系统中,进行流量削峰的优化吧。

 

 

往期文章推荐:

中间件专辑:

什么是消息中间件?主要作用是什么?

常见的消息中间件有哪些?你们是怎么进行技术选型的?

你懂RocketMQ 的架构原理吗?

聊一聊RocketMQ的注册中心NameServer

Broker的主从架构是怎么实现的?

RocketMQ生产部署架构如何设计

RabbitMQ和Kafka的高可用集群原理

RocketMQ的发送模式和消费模式

算法专辑:

和同事谈谈Flood Fill 算法

详解股票买卖算法的最优解(一)

详解股票买卖算法的最优解(二)

聊一聊二分查找法

 

posted @ 2020-09-16 15:36  H.U.C-王子  阅读(1733)  评论(2编辑  收藏  举报