亿级流量系统架构之如何设计每秒十万查询的高并发架构【石杉的架构笔记】

欢迎关注我的公众号:石杉的架构笔记(ID:shishan100)面试

周一至周五早8点半!精品技术文章准时送上!算法


亿级流量架构专栏:数据库

1、前情回顾

上篇文章(亿级流量系统架构之如何设计承载百亿流量的高性能架构)聊了一下系统架构中,百亿流量级别高并发写入场景下,如何承载这种高并发写入,同时如何在高并发写入的背景下还能保证系统的超高性能计算。后端

这篇文章我们继续来聊一下,百亿级别的海量数据场景下还要支撑每秒十万级别的高并发查询,这个架构该如何演进和设计?缓存

我们先来看看目前系统已经演进到了什么样的架构,你们看看下面的图:性能优化

首先回顾一下,整个架构右侧部分演进到的那个程度,其实已经很是的不错了,由于百亿流量,每秒十万级并发写入的场景,使用MQ限流削峰、分布式KV集群给抗住了。服务器

接着使用了计算与存储分离的架构,各个Slave计算节点会负责提取数据到内存中,基于自研的SQL内存计算引擎完成计算。同时采用了数据动静分离的架构,静态数据所有缓存,动态数据自动提取,保证了尽量把网络请求开销下降到最低。网络

另外,经过自研的分布式系统架构,包括数据分片和计算任务分布式执行、弹性资源调度、分布式高容错机制、主备自动切换机制,都能保证整套系统的任意按需扩容,高性能、高可用的的运行。架构

下一步,我们得来研究研究架构里左侧的部分了。并发

2、日益膨胀的离线计算结果

其实你们会注意到,在左侧还有一个MySQL,那个MySQL就是用来承载实时计算结果和离线计算结果放在里面汇总的。

终端的商家用户就能够随意的查询MySQL里的数据分析结果,支撑本身的决策,他能够看当天的数据分析报告,也能够看历史上任何一段时期内的数据分析报告。

可是那个MySQL在早期可能还好一些,由于其实存放在这个MySQL里的数据量相对要小一些,毕竟是计算后的一些结果罢了。可是到了中后期,这个MySQL但是也朝不保夕了。

给你们举一个例子,离线计算链路里,若是天天增量数据是1000万,那么天天计算完之后的结果大概只有50万,天天50万新增数据放入MySQL,其实仍是能够接受的。

可是若是天天增量数据是10亿,那么天天计算完之后的结果大体会是千万级,你能够算他是计算结果有5000万条数据吧,天天5000万增量数据写入左侧的MySQL中,你以为是啥感受?

能够给你们说说系统当时的状况,基本上就是,单台MySQL服务器的磁盘存储空间很快就要接近满掉,并且单表数据量都是几亿、甚至十亿的级别。

这种量级的单表数据量,你以为用户查询数据分析报告的时候,体验能好么?基本当时一次查询都是几秒钟的级别。很慢。

更有甚者,出现过用户一次查询要十秒的级别,甚至几十秒,上分钟的级别。很崩溃,用户体验不好,远远达不到付费产品的级别。

因此解决了右侧的存储和计算的问题以后,左侧的查询的问题也迫在眉睫。新一轮的重构,势在必行!

3、分库分表 + 读写分离

首先就是老一套,分库分表 + 读写分离,这个基本是基于MySQL的架构中,必经之路了,毕竟实施起来难度不是特别的高,并且速度较快,效果比较显著。

整个的思路和以前第一篇文章(《大型系统架构演进之如何支撑百亿级数据的存储与计算》)讲的基本一致。

说白了,就是分库后,每台主库能够承载部分写入压力,单库的写并发会下降;其次就是单个主库的磁盘空间能够下降负载的数据量,不至于很快就满了;

而分表以后,单个数据表的数据量能够下降到百万级别,这个是支撑海量数据以及保证高性能的最佳实践,基本两三百万的单表数据量级仍是合理的。

而后读写分离以后,就能够将单库的读写负载压力分离到主库和从库多台机器上去,主库就承载写负载,从库就承载读负载,这样避免单库所在机器的读写负载太高,致使CPU负载、IO负载、网络负载太高,最后搞得数据库机器宕机。

首先这么重构一下数据库层面的架构以后,效果就好的多了。由于单表数据量下降了,那么用户查询的性能获得很大的提高,基本能够达到1秒之内的效果。


4、每秒10万查询的高并发挑战

上面那套初步的分库分表+读写分离的架构确实支撑了一段时间,可是慢慢的那套架构又暴露出来了弊端出来了,由于商家用户都是开了数据分析页面以后,页面上有js脚本会每隔几秒钟就发送一次请求到后端来加载最新的数据分析结果。

此时就有一个问题了,渐渐的查询MySQL的压力愈来愈大,基本上可预见的范围是朝着每秒10级别去走。

可是咱们分析了一下,其实99%的查询,都是页面JS脚本自动发出刷新当日数据的查询。只有1%的查询是针对昨天之前的历史数据,用户手动指定查询范围后来查询的。

可是如今的这个架构之下,咱们是把当日实时数据计算结果(表明了热数据)和历史离线计算结果(表明了冷数据)都放在一块儿的,因此你们能够想象一下,热数据和冷数据放在一块儿,而后对热数据的高并发查询占到了99%,那这样的架构还合理吗?

固然不合理,咱们须要再次重构系统架构。

5、 数据的冷热分离架构

针对上述提到的问题,很明显要作的一个架构重构就是冷热数据分离。也就是说,将今日实时计算出来的热数据放在一个MySQL集群里,将离线计算出来的冷数据放在另一个MySQL集群里。

而后开发一个数据查询平台,封装底层的多个MySQL集群,根据查询条件动态路由到热数据存储或者是冷数据存储。

经过这个步骤的重构,咱们就能够有效的将热数据存储中单表的数据量下降到更少更少,有的单表数据量可能就几十万,由于将离线计算的大量数据结果从表里剥离出去了,放到另一个集群里去。此时你们可想而知,效果固然是更好了。

由于热数据的单表数据量减小了不少,当时的一个最明显的效果,就是用户99%的查询都是针对热数据存储发起的,性能从原来的1秒左右下降到了200毫秒之内,用户体验提高,你们感受更好了。


6、自研Elasticsearch+HBase+纯内存的查询引擎

架构演进到这里,看起来好像还不错,可是其实问题仍是不少。由于到了这个阶段,系统遇到了另一个较为严重的问题:冷数据存储,若是彻底用MySQL来承载是很不靠谱的。冷数据的数据量是日增加不断增长,并且增速很快,天天都新增几千万。

所以你的MySQL服务器将会面临不断的须要扩容的问题,并且若是为了支撑这1%的冷数据查询请求,不断的扩容增长高配置的MySQL服务器,你们以为靠谱么?

确定是不合适的!

要知道,大量分库分表后,MySQL大量的库和表维护起来是至关麻烦的,修改个字段?加个索引?这都是一场麻烦事儿。

此外,由于对冷数据的查询,通常都是针对大量数据的查询,好比用户会选择过去几个月,甚至一年的数据进行分析查询,此时若是纯用MySQL仍是挺灾难性的。

由于当时明显发现,针对海量数据场景下,一会儿查询分析几个月或者几年的数据,性能是极差的,仍是很容易搞成几秒甚至几十秒才出结果。

所以针对这个冷数据的存储和查询的问题,咱们最终选择了自研一套基于NoSQL来存储,而后基于NoSQL+内存的SQL计算引擎。

具体来讲,咱们会将冷数据所有采用ES+HBase来进行存储,ES中主要存放要对冷数据进行筛选的各类条件索引,好比日期以及各类维度的数据,而后HBase中会存放全量的数据字段。

由于ES和HBase的原生SQL支持都不太好,所以咱们直接自研了另一套SQL引擎,专门支持这种特定的场景,就是基本没有多表关联,就是对单个数据集进行查询和分析,而后支持NoSQL存储+内存计算。

这里有一个先决条件,就是若是要作到对冷数据所有是单表类的数据集查询,必需要在冷数据进入NoSQL存储的时候,所有基于ES和HBase的特性作到多表入库关联,进数据存储就所有作成大宽表的状态,将数据关联所有上推到入库时完成,而不是在查询时进行。

对冷数据的查询,咱们自研的SQL引擎首先会根据各类where条件先走ES的分布式高性能索引查询,ES能够针对海量数据高性能的检索出来须要的那部分数据,这个过程用ES作是最合适的。

接着就是将检索出来的数据对应的完整的各个数据字段,从HBase里提取出来,拼接成完成的数据。

而后就是将这份数据集放在内存里,进行复杂的函数计算、分组聚合以及排序等操做。

上述操做,所有基于自研的针对这个场景的查询引擎完成,底层基于Elasticsearch、HBase、纯内存来实现。

7、实时数据存储引入缓存集群

好了,到此为止,冷数据的海量数据存储、高性能查询的问题,就解决了。接着回过头来看看当日实时数据的查询,其实实时数据的每日计算结果不会太多,并且写入并发不会特别特别的高,每秒上万也就差很少了。

所以这个背景下,就是用MySQL分库分表来支撑数据的写入、存储和查询,都没问题。

可是有一个小问题,就是说每一个商家的实时数据其实不是频繁的变动的,在一段时间内,可能压根儿没变化,所以不须要高并发请求,每秒10万级别的所有落地到数据库层面吧?要全都落地到数据库层面,那可能要给每一个主库挂载不少从库来支撑高并发读。

所以这里咱们引入了一个缓存集群,实时数据每次更新后写入的时候,都是写数据库集群同时还写缓存集群的,是双写的方式。

而后查询的时候是优先从缓存集群来走,此时基本上90%以上的高并发查询都走缓存集群了,而后只有10%的查询会落地到数据库集群。

8、阶段性总结

好了,到此为止,这个架构基本左边也都重构完毕:

  • 热数据基于缓存集群+数据库集群来承载高并发的每秒十万级别的查询
  • 冷数据基于ES+HBase+内存计算的自研查询引擎来支撑海量数据存储以及高性能查询。

经实践,整个效果很是的好。用户对热数据的查询基本可能是几十毫秒的响应速度,对冷数据的查询基本都是200毫秒之内的响应速度。

9、下一阶段的展望

其实架构演进到这里已经很不容易了,由于看似这么一张图,里面涉及到无数的细节和技术方案的落地,须要一个团队耗费至少1年的时间才能作到这个程度。

可是接下来,咱们要面对的,就是高可用的问题,由于付费级的产品,咱们必需要保证超高的可用性,99.99%的可用性,甚至是99.999%的可用性。

可是越是复杂的系统,越容易出现问题,对应的高可用架构就越是复杂无比,所以下篇文章,咱们聊聊:《亿级流量系统架构之如何设计全链路99.99%高可用架构》


END


一大波微服务、分布式、高并发、高可用原创系列

文章正在路上,欢迎扫描下方二维码,持续关注:


石杉的架构笔记(id:shishan100)

十余年BAT架构经验倾囊相授

推荐阅读:

一、拜托!面试请不要再问我Spring Cloud底层原理

二、【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?

三、【性能优化之道】每秒上万并发下的Spring Cloud参数优化实战

四、微服务架构如何保障双11狂欢下的99.99%高可用

五、兄弟,用大白话告诉你小白都能听懂的Hadoop架构原理

六、大规模集群下Hadoop NameNode如何承载每秒上千次的高并发访问

七、【性能优化的秘密】Hadoop如何将TB级大文件的上传性能优化上百倍

八、拜托,面试请不要再问我TCC分布式事务的实现原理坑爹呀!

九、【坑爹呀!】最终一致性分布式事务如何保障实际生产中99.99%高可用?

十、拜托,面试请不要再问我Redis分布式锁的实现原理!

十一、【眼前一亮!】看Hadoop底层算法如何优雅的将大规模集群性能提高10倍以上?

十二、亿级流量系统架构之如何支撑百亿级数据的存储与计算

1三、亿级流量系统架构之如何设计高容错分布式计算系统

1四、亿级流量系统架构之如何设计承载百亿流量的高性能架构

相关文章
相关标签/搜索