大厂面试必问:如何设计一个扛高并发的系统?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 高并发系统是指:在短时间内同时有大量用户请求访问系统,需要系统能够快速、稳定地响应这些请求。本文将讲述如何设计一个扛高并发的系统。

前言

大家好,我是路由器没有路

三年前,我曾前往字节跳动参加面试。在三面面试环节中,我遇到了一道场景设计题目:如何设计一个高并发系统?

当时我的回答比较简略,但最近我朋友在准备面试,问我关于大厂面试的一些经验,于是我回想起来,因此整理出了 8 个在设计高并发系统时需要考虑的技术点或者说因素

相信这些能够帮助大家更好地理解和应对高并发系统的场景。

57ea3f93-4530-4bdc-9cbc-23433f3c63bc.png

  • 公众号:Go 键盘侠

什么是高并发系统?

高并发系统是指:在短时间内同时有大量用户请求访问系统,需要系统能够快速、稳定地响应这些请求

高并发系统案例

例如,当某个电商平台在双十一期间推出大量优惠活动时,可能会有成千上万的用户同时访问该平台,这就是一个高并发系统。

在这种情况下,如果系统无法快速处理这些请求,就会导致用户体验下降,甚至导致系统崩溃。

因此,高并发系统需要具备快速、稳定地响应大量请求的能力,以保证系统的正常运行和用户体验。

高并发带来的问题

1.系统压力增大:高并发请求会导致系统压力增大,可能会导致系统崩溃或运行缓慢。

2.响应时间延长:高并发请求会导致系统响应时间延长,用户体验下降。

3.数据不一致:高并发请求可能会导致数据不一致,例如在多个请求同时对同一数据进行操作时,可能会导致数据出现异常。

4.资源浪费:高并发请求可能会导致系统资源浪费,例如某些请求可能会占用过多的内存或 CPU 资源,导致其他请求无法正常运行。

而今天要讲的就是该如何设计一个高并发系统,需要考虑哪些因素,才能处理好高并发带来的问题,以保证系统的高并发处理能力。

1.分而治之:系统拆分

系统拆分(微服务拆分)简单来说就是将一个系统拆分为多个子系统,换句话说就是将一个单体的应用按照功能单一性拆分为多个服务模块

这样拆分后的每个系统连一个数据库,这样本来就一个库,现在多个数据库,也是可以扛高并发的。

例如,在商城系统中,可以将用户系统、订单系统、商品系统等功能拆分为不同的服务模块,从而实现请求流量的分摊,提高系统的并发处理能力

商城系统拆分.png

2.访问提速:加缓存

缓存是现代计算机系统中普遍存在的技术,无论是操作系统、浏览器还是一些复杂的中间件,都可以看到缓存的应用。

大部分的高并发场景,都是读多写少,要想提高数据的访问速度,那系统必须得加缓存。

我们使用缓存的主要目的是提高系统接口的性能,特别是在高并发场景下,缓存可以帮助系统支持更多的用户同时访问。

常见的缓存技术包括 Redis 缓存、JVM 本地缓存、memcached 等。

就以 Redis 为例,它单机就可以轻松应对几万的并发请求,因此在读取场景的业务中,使用缓存可以有效地抗击高并发请求。

但是使用缓存时,以下问题是需要考虑的:

  • 缓存数据一致性
  • 缓存雪崩
  • 缓存穿透
  • 缓存击穿

前面我专门写过两篇关于缓存问题的文章,可以看下:

3.削峰处理:使用消息队列 MQ

在系统中可能会出现高并发写的场景,例如在某个业务操作中需要频繁地对数据库进行增删改操作,这可能会导致系统崩溃。

如果使用 Redis 缓存来承载写操作,可能会出现数据被 LRU 淘汰的问题,而且 Redis 缓存不支持事务,因此不适合承载复杂写业务逻辑的场景

在这种情况下,当然你可能会考虑直接使用 MySQL 来承载写操作,但是 MySQL 数据库需要注意控制写操作的并发数,避免对 MySQL 造成过大的压力。

为了解决高并发写场景的问题,可以使用消息队列(MQ)来异步处理写请求

将大量的写请求灌入 MQ 中,让下游系统循序渐进地消费这些请求,控制在 MySQL 承载范围之内。

MQ 单机可以抗击几万并发请求,因此在处理高并发写场景时,使用 MQ 可以提升系统的吞吐量和并发性能

消息队列mq.png

4.数据分离:分库分表

如果业务发展的比较迅速的话,数据库将会成为性能的瓶颈

也就是说,当业务的体量上来了,MySQL 数据库单机的磁盘容量可能会达到上限。

此外,数据库连接数也是有限的,因此在高并发场景下,大量请求访问数据库,MySQL 单机无法承受。在高并发场景下,可能会出现too many connections 的报错。

因此,为了应对高并发的挑战,需要将高并发系统拆分为多个数据库,多个库来扛更高的并发,以提高系统的并发处理能力

如果单表数据量也非常大,存储和查询的性能就也会遇到瓶颈。

在进行了分库优化之后,如果提升性能的效果不太大,就需要考虑进行分表操作了

一般来说,当单表数据量达到千万级别时,就需要考虑进行分表操作了,将数据分散到多个表中,以提高 SQL 查询性能

可以看下我前面写的关于分库分表的文章:

数据库之分库分表的一些总结

5.读多写少场景:读写分离

读写分离是指将数据库中的读操作和写操作分别分配到不同的数据库实例上进行处理的技术

读写分离的好处是可以提高系统的并发处理能力和性能,因为读操作和写操作通常具有不同的特点,读操作通常比较频繁,而写操作通常比较耗时。

因此,将读操作和写操作分别分配到不同的数据库实例上进行处理,可以有效地提高系统的并发处理能力和性能。

例如,在一个电商平台中,用户经常会进行商品浏览、搜索等读操作,而商品的添加、修改、删除等写操作则相对较少。

此时,可以将读操作和写操作分别分配到不同的数据库实例上进行处理,以提高系统的并发处理能力和性能。

另外,读写分离还可以提高系统的可用性和可靠性。当主库出现故障时,从库可以接管主库的读操作,保证系统的正常运行。

6.异构数据索引:ElasticSearch

ElasticSearch,简称 ES,是一种分布式的搜索和分析引擎,可以随意扩容,并且天然支持高并发。

由于 ES 可以动态地扩容并增加更多的机器来处理更高的并发请求,因此它天然地具备了处理高并发请求的能力。

因此,对于一些比较简单的查询、统计类的操作,可以考虑使用 ES 来承载。此外,对于一些全文搜索类的操作,也可以使用 ES 来承载。

前面也写过两遍文章关于 ES 的介绍和使用规范:

7.静态资源访问:CDN

什么是 CDN?

CDN 是指内容分发网络,是一种将内容分发到全球各地的网络架构。

CDN 可以将网站的静态资源(如图片、CSS、JavaScript 等文件)缓存到全球各地的服务器上,当用户请求这些资源时,可以从离用户最近的服务器上获取资源,从而提高资源的访问速度和用户的访问体验

CDN 的作用有哪些?

CDN 的主要作用是:

  • 提高网站的访问速度
  • 降低带宽成本
  • 提高可用性。

同样,在高并发场景下,CDN 可以发挥重要的作用。

由于高并发场景下会有大量的用户同时访问网站,如果所有的请求都直接访问源站,就会导致源站的带宽和服务器资源受到过大的压力,从而导致网站的访问速度变慢或者出现宕机等问题。

因此,在高并发场景下,使用 CDN 可以将流量分散到全球各地的服务器上,从而减轻源站的压力,提高网站的访问速度和可用性

8.微服务治理:上容器、k8s 弹性伸缩管理

前面写了几篇关于容器和 K8S 的文章,可以看看,这里就不再赘述概念性的东西。

假设有一个电商平台,该平台的用户量在特定的时间段内会出现高峰期,例如双十一、618 等大型促销活动期间。

在这些高峰期内,平台需要处理大量的并发请求,因此可以使用容器化技术和 k8s 弹性伸缩技术来解决高并发问题

具体而言,该电商平台可以将应用程序容器化,并使用 k8s 进行容器编排、服务发现和负载均衡

当用户发起请求时,请求会被 k8s 自动分发到不同的容器实例上,从而实现负载均衡。

此外,该电商平台还可以使用 k8s 的自动伸缩功能,在高峰期自动增加容器实例的数量,以应对高并发请求。当高峰期结束后,k8s 会自动减少容器实例的数量,以避免资源浪费。

通过使用容器化技术和 k8s 弹性伸缩技术,该电商平台可以提高系统的稳定性、性能和可用性,从而提高性能和实现更好的用户体验。

总结

如何设计一个扛高并发的系统,是每个上进程序员都需要考虑的问题。

在设计高并发系统时,可以从上面讲的 8 个方面去考虑,从而实现系统的高并发处理能力和可靠性。

当然还有其它需要考虑的,比如:降级、熔断、限流等。

相关文章
|
5月前
|
消息中间件 算法 数据库
架构设计篇问题之商城系统高并发写的问题如何解决
架构设计篇问题之商城系统高并发写的问题如何解决
|
2月前
|
缓存 算法 架构师
京东面试:如何设计600Wqps高并发ID?如何解决时钟回拨问题?
资深架构师尼恩在其读者交流群中分享了关于分布式ID系统的设计与实现,特别是针对高并发场景下的解决方案。他强调了分布式ID系统在高并发核心组件中的重要性,并详细介绍了百度的UidGenerator,这是一个基于Snowflake算法改进的Java实现,旨在解决分布式系统中的唯一ID生成问题。UidGenerator通过自定义workerId位数和初始化策略,支持虚拟化环境下的实例自动重启和漂移,其单机QPS可达600万。此外尼恩的技术分享不仅有助于提升面试表现,还能帮助开发者在实际项目中应对高并发挑战。
京东面试:如何设计600Wqps高并发ID?如何解决时钟回拨问题?
|
2月前
|
C语言
经典面试题:嵌入式系统中经常要用到无限循环,怎么样用C编写死循环呢
在嵌入式系统开发中,无限循环常用于持续运行特定任务或监听事件。使用C语言实现死循环很简单,可以通过`while(1)`或`for(;;)`的结构来编写。例如:`while (1) { /* 循环体代码 */ }`,这种写法明确简洁,适用于需要持续执行的任务或等待中断的场景。
|
2月前
|
存储 消息中间件 缓存
系统设计面试参考-设计Spotify系统
【10月更文挑战第4天】支持用户将自己喜欢的音乐、专辑、播放列表等分享到社交媒体平台,如 Facebook、Twitter、Instagram 等。分享内容可以包括音乐链接、封面图片、简介等信息,吸引更多的用户来使用 Spotify 系统。同时,系统可以跟踪分享的效果,如点击量、转化率等,以便评估社交分享对系统推广的贡献。
|
2月前
|
Java Go 云计算
Go语言在云计算和高并发系统中的卓越表现
【10月更文挑战第10天】Go语言在云计算和高并发系统中的卓越表现
|
4月前
|
监控 算法 Java
企业应用面临高并发等挑战,优化Java后台系统性能至关重要
随着互联网技术的发展,企业应用面临高并发等挑战,优化Java后台系统性能至关重要。本文提供三大技巧:1)优化JVM,如选用合适版本(如OpenJDK 11)、调整参数(如使用G1垃圾收集器)及监控性能;2)优化代码与算法,减少对象创建、合理使用集合及采用高效算法(如快速排序);3)数据库优化,包括索引、查询及分页策略改进,全面提升系统效能。
55 0
|
5月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
70 1
|
5月前
|
消息中间件 算法 NoSQL
面试题Kafka问题之Kafka保证系统的可用性如何解决
面试题Kafka问题之Kafka保证系统的可用性如何解决
50 0
|
5月前
|
监控 网络协议 Java
Java面试题:解释Java NIO与BIO的区别,以及NIO的优势和应用场景。如何在高并发应用中实现NIO?
Java面试题:解释Java NIO与BIO的区别,以及NIO的优势和应用场景。如何在高并发应用中实现NIO?
83 0
|
5月前
|
设计模式 存储 缓存
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
62 0