在服务端对秒杀商品进行本地缓存,不需要再调用依赖系统的后台服务获取数据,甚至不需要去公共的缓存集群中查询数据,这样不仅可以减少系统调用,而且能够避免压垮公共缓存集群。
增加系统限流保护,防止最坏情况发生。
经过这些优化,系统架构变成了下图中的样子。在这里,我们对页面进行了进一步的静态化,秒杀过程中不需要刷新整个页面,而只需要向服务端请求很少的动态数据。而且,最关键的详情和交易系统都增加了本地缓存,来提前缓存秒杀商品的信息,热点数据库也做了独立部署,等等。
从前面的几次升级来看,其实越到后面需要定制的地方越多,也就是越“不通用”。例如,把秒杀商品缓存在每台机器的内存中,这种方式显然不适合太多的商品同时进行秒杀的情况,因为单机的内存始终有限。所以要取得极致的性能,就要在其他地方(比如,通用性、易用性、成本等方面)有所牺牲。
02 | 如何才能做好动静分离?有哪些方案可选?数据的动静分离。不知道你之前听过这个解决方案吗?不管你有没有听过,我都建议你先停下来思考动静分离的价值。如果你的系统还没有开始应用动静分离的方案,那你也可以想想为什么没有,是之前没有想到,还是说业务体量根本用不着?不过我可以确信地说,如果你在一个业务飞速发展的公司里,并且你在深度参与公司内类秒杀类系统的架构或者开发工作,那么你迟早会想到动静分离的方案。为什么?很简单,秒杀的场景中,对于系统的要求其实就三个字:快、准、稳。
那怎么才能“快”起来呢?我觉得抽象起来讲,就只有两点,一点是提高单次请求的效率,一点是减少没必要的请求。今天我们聊到的“动静分离”其实就是瞄着这个大方向去的。
不知道你是否还记得,最早的秒杀系统其实是要刷新整体页面的,但后来秒杀的时候,你只要点击“刷新抢宝”按钮就够了,这种变化的本质就是动静分离,分离之后,客户端大幅度减少了请求的数据量。这不自然就“快”了吗?
那到底什么才是动静分离呢?所谓“动静分离”,其实就是把用户请求的数据(如 HTML 页面)划分为“动态数据”和“静态数据”。
简单来说,“动态数据”和“静态数据”的主要区别就是看页面中输出的数据是否和 URL、浏览者、时间、地域相关,以及是否含有 Cookie 等私密数据。比如说:
很多媒体类的网站,某一篇文章的内容不管是你访问还是我访问,它都是一样的。所以它就是一个典型的静态数据,但是它是个动态页面。
我们如果现在访问淘宝的首页,每个人看到的页面可能都是不一样的,淘宝首页中包含了很多根据访问者特征推荐的信息,而这些个性化的数据就可以理解为动态数据了。
这里再强调一下,我们所说的静态数据,不能仅仅理解为传统意义上完全存在磁盘上的 HTML 页面,它也可能是经过 Java 系统产生的页面,但是它输出的页面本身不包含上面所说的那些因素。也就是所谓“动态”还是“静态”,并不是说数据本身是否动静,而是数据中是否含有和访问者相关的个性化数据。
还有一点要注意,就是页面中“不包含”,指的是“页面的 HTML 源码中不含有”,这一点务必要清楚。理解了静态数据和动态数据,我估计你很容易就能想明白“动静分离”这个方案的来龙去脉了。分离了动静数据,我们就可以对分离出来的静态数据做缓存,有了缓存之后,静态数据的“访问效率”自然就提高了。
那么,怎样对静态数据做缓存呢?我在这里总结了几个重点。
第一,你应该把静态数据缓存到离用户最近的地方。静态数据就是那些相对不会变化的数据,因此我们可以把它们缓存起来。缓存到哪里呢?常见的就三种,用户浏览器里、CDN 上或者在服务端的 Cache 中。你应该根据情况,把它们尽量缓存到离用户最近的地方。
第二,静态化改造就是要直接缓存 HTTP 连接。相较于普通的数据缓存而言,你肯定还听过系统的静态化改造。静态化改造是直接缓存 HTTP 连接而不是仅仅缓存数据,如下图所示,Web 代理服务器根据请求 URL,直接取出对应的 HTTP 响应头和响应体然后直接返回,这个响应过程简单得连 HTTP 协议都不用重新组装,甚至连 HTTP 请求头也不需要解析。