字节三面:如何设计一个高并发系统

news2025/1/10 23:40:08

前言

大家好,我是田螺

记得很久之前,去面试过字节跳动。被三面的面试官问了一道场景设计题目:如何设计一个高并发系统。当时我回答得比较粗糙,最近回想起来,所以整理了设计高并发系统的15个锦囊,相信大家看完会有帮助的。

如何理解高并发系统

所谓设计高并发系统,就是设计一个系统,保证它整体可用的同时,能够处理很高的并发用户请求,能够承受很大的流量冲击

我们要设计高并发的系统,那就需要处理好一些常见的系统瓶颈问题,如内存不足、磁盘空间不足,连接数不够,网络宽带不够等等,以应对突发的流量洪峰。

1. 分而治之,横向扩展

如果你只部署一个应用,只部署一台服务器,那抗住的流量请求是非常有限的。并且,单体的应用,有单点的风险,如果它挂了,那服务就不可用了。

因此,设计一个高并发系统,我们可以分而治之,横向扩展。也就是说,采用分布式部署的方式,部署多台服务器,把流量分流开,让每个服务器都承担一部分的并发和流量,提升整体系统的并发能力

2. 微服务拆分(系统拆分)

要提高系统的吞吐,提高系统的处理并发请求的能力。除了采用分布式部署的方式外,还可以做微服务拆分,这样就可以达到分摊请求流量的目的,提高了并发能力。

所谓的微服务拆分,其实就是把一个单体的应用,按功能单一性,拆分为多个服务模块。比如一个电商系统,拆分为用户系统、订单系统、商品系统等等

3. 分库分表

当业务量暴增的话,MySQL单机磁盘容量会撑爆。并且,我们知道数据库连接数是有限的。在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!高并发场景下,会出现too many connections报错。

所以高并发的系统,需要考虑拆分为多个数据库,来抗住高并发的毒打。而假如你的单表数据量非常大,存储和查询的性能就会遇到瓶颈了,如果你做了很多优化之后还是无法提升效率的时候,就需要考虑做分表了。一般千万级别数据量,就需要分表,每个表的数据量少一点,提升SQL查询性能。

当面试官问要求你设计一个高并发系统的时候,一般都要说到分库分表这个点。

之前写了分库分表15连问,为了应对面试官追问到底,大家可以顺便复习一下分库分表的相关经典面试题哈,可以看我这篇文章:分库分表经典15连问

4. 池化技术

在高并发的场景下,数据库连接数可能成为瓶颈,因为连接数是有限的。

我们的请求调用数据库时,都会先获取数据库的连接,然后依靠这个连接来查询数据,搞完收工,最后关闭连接,释放资源。如果我们不用数据库连接池的话,每次执行SQL,都要创建连接和销毁连接,这就会导致每个查询请求都变得更慢了,相应的,系统处理用户请求的能力就降低了。

因此,需要使用池化技术,即数据库连接池、HTTP 连接池、Redis 连接池等等。使用数据库连接池,可以避免每次查询都新建连接,减少不必要的资源开销,通过复用连接池,提高系统处理高并发请求的能力

同理,我们使用线程池,也能让任务并行处理,更高效地完成任务。大家可以看下我之前线程池的这篇文章,到时候面试官问到这块时,刚好可以扩展开来讲

  • 面试必备:Java线程池解析
  • 细数线程池的10个坑

5. 主从分离

通常来说,一台单机的MySQL服务器,可以支持500左右的TPS10000左右的QPS,即单机支撑的请求访问是有限的。因此你做了分布式部署,部署了多台机器,部署了主数据库、从数据库。

但是,如果双十一搞活动,流量肯定会猛增的。如果所有的查询请求,都走主库的话,主库肯定扛不住,因为查询请求量是非常非常大的。因此一般都要求做主从分离,然后实时性要求不高的读请求,都去读从库,写的请求或者实时性要求高的请求,才走主库。这样就很好保护了主库,也提高了系统的吞吐。

当然,如果回答了主从分离,面试官可能扩展开问你主从复制原理,问你主从延迟问题等等,这块大家需要全方位复习好哈。可以去看看我之前的这篇文章

面试必备:聊聊MySQL的主从

6. 使用缓存

无论是操作系统,浏览器,还是一些复杂的中间件,你都可以看到缓存的影子。我们使用缓存,主要是提升系统接口的性能,这样高并发场景,你的系统就可以支持更多的用户同时访问。

常用的缓存包括:Redis缓存,JVM本地缓存,memcached等等。就拿Redis来说,它单机就能轻轻松松应对几万的并发,你读场景的业务,可以用缓存来抗高并发。

缓存虽然用得爽,但是要注意缓存使用的一些问题

  • 缓存与数据库的一致性问题
  • 缓存雪崩
  • 缓存穿透
  • 缓存击穿

如果大家打算使用Redis的话,需要知道一些注意点,可以看下我之前的这篇文章哈,挺好的。使用Redis,你必须知道的21个注意要点

7. CDN,加速静态资源访问

商品图片,icon等等静态资源,可以对页面做静态化处理,减少访问服务端的请求。如果用户分布在全国各地,有的在上海,有的在深圳,地域相差很远,网速也各不相同。为了让用户最快访问到页面,可以使用CDNCDN可以让用户就近获取所需内容。

什么是CDN?

Content Delivery Network/Content Distribution Network,翻译过来就是内容分发网络,它表示将静态资源分发到位于多个地理位置机房的服务器,可以做到数据就近访问,加速了静态资源的访问速度,因此让系统更好处理正常别的动态请求。

8. 消息队列,削锋

我们搞一些双十一、双十二等运营活动时,需要避免流量暴涨,打垮应用系统的风险。因此一般会引入消息队列,来应对高并发的场景

假设你的应用系统每秒最多可以处理2k个请求,每秒却有5k的请求过来,可以引入消息队列,应用系统每秒从消息队列拉2k请求处理得了。

有些伙伴担心这样可能会出现消息积压的问题:

  • 首先,搞一些运营活动,不会每时每刻都那么多请求过来你的系统(除非有人恶意攻击),高峰期过去后,积压的请求可以慢慢处理;
  • 其次,如果消息队列长度超过最大数量,可以直接抛弃用户请求或跳转到错误页面;

9. ElasticSearch

Elasticsearch,大家都使用得比较多了吧,一般搜索功能都会用到它。它是一个分布式、高扩展、高实时的搜索与数据分析引擎,简称为ES

我们在聊高并发,为啥聊到ES呢? 因为ES可以扩容方便,天然支撑高并发。当数据量大的时候,不用动不动就加机器扩容,分库等等,可以考虑用ES来支持简单的查询搜索、统计类的操作。

10. 降级熔断

熔断降级是保护系统的一种手段。当前互联网系统一般都是分布式部署的。而分布式系统中偶尔会出现某个基础服务不可用,最终导致整个系统不可用的情况, 这种现象被称为服务雪崩效应

比如分布式调用链路A->B->C....,下图所示:

如果服务C出现问题,比如是因为慢SQL导致调用缓慢,那将导致B也会延迟,从而A也会延迟。堵住的A请求会消耗占用系统的线程、IO、CPU等资源。当请求A的服务越来越多,占用计算机的资源也越来越多,最终会导致系统瓶颈出现,造成其他的请求同样不可用,最后导致业务系统崩溃。

为了应对服务雪崩, 常见的做法是熔断和降级。最简单是加开关控制,当下游系统出问题时,开关打开降级,不再调用下游系统。还可以选用开源组件Hystrix来支持。

你要保证设计的系统能应对高并发场景,那肯定要考虑熔断降级逻辑进来。

11. 限流

限流也是我们应对高并发的一种方案。我们当然希望,在高并发大流量过来时,系统能全部请求都正常处理。但是有时候没办法,系统的CPU、网络带宽、内存、线程等资源都是有限的。因此,我们要考虑限流。

如果你的系统每秒扛住的请求是一千,如果一秒钟来了十万请求呢?换个角度就是说,高并发的时候,流量洪峰来了,超过系统的承载能力,怎么办呢?

这时候,我们可以采取限流方案。就是为了保护系统,多余的请求,直接丢弃。

什么是限流:在计算机网络中,限流就是控制网络接口发送或接收请求的速率,它可防止DoS攻击和限制Web爬虫。限流,也称流量控制。是指系统在面临高并发,或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的稳定性。

可以使用GuavaRateLimiter单机版限流,也可以使用Redis分布式限流,还可以使用阿里开源组件sentinel限流。

面试的时候,你说到限流这块的话?面试官很大概率会问你限流的算法,因此,大家在准备面试的时候,需要复习一下这几种经典的限流算法哈,可以看下我之前的这篇文章,面试必备:4种经典限流算法讲解

12. 异步

回忆一下什么是同步,什么是异步呢?以方法调用为例,它代表调用方要阻塞等待被调用方法中的逻辑执行完成。这种方式下,当被调用方法响应时间较长时,会造成调用方长久的阻塞,在高并发下会造成整体系统性能下降甚至发生雪崩。异步调用恰恰相反,调用方不需要等待方法逻辑执行完成就可以返回执行其他的逻辑,在被调用方法执行完毕后再通过回调、事件通知等方式将结果反馈给调用方。

因此,设计一个高并发的系统,需要在恰当的场景使用异步。如何使用异步呢?后端可以借用消息队列实现。比如在海量秒杀请求过来时,先放到消息队列中,快速相应用户,告诉用户请求正在处理中,这样就可以释放资源来处理更多的请求。秒杀请求处理完后,通知用户秒杀抢购成功或者失败。

13. 常规的优化

设计一个高并发的系统,需要设计接口的性能足够好,这样系统在相同时间,就可以处理更多的请求。当说到这里的话,大家就可以跟面试官说说接口优化的一些方案了。大家可以看下我的这篇文章哈:实战总结!18种接口优化方案的总结

14. 压力测试确定系统瓶颈

设计高并发系统,离不开最重要的一环,就是压力测试。就是在系统上线前,需要对系统进行压力测试,测清楚你的系统支撑的最大并发是多少,确定系统的瓶颈点,让自己心里有底,最好预防措施。

压测完要分析整个调用链路,性能可能出现问题是网络层(如带宽)、Nginx层、服务层、还是数据路缓存等中间件等等。

loadrunner是一款不错的压力测试工具,jmeter则是接口性能测试工具,都可以来做下压测。

15. 应对突发流量峰值:扩容+切流量

如果是突发的流量高峰,除了降级、限流保证系统不跨,我们可以采用这两种方案,保证系统尽可能服务用户:

  • 扩容:比如增加从库、提升配置的方式,提升系统/组件的流量承载能力。比如增加MySQL、Redis从库来处理查询请求。
  • 切流量:服务多机房部署,如果高并发流量来了,把流量从一个机房切换到另一个机房。

参考与感谢

  • 极客时间高并发系统设计 40 问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/146372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【EHub_tx1_tx2_E100】Ubuntu18.04 + ROS_ Melodic + 万集716 单线激光 测试

简介:介绍 万集716 单线激光 在EHub_tx1_tx2_E100载板,TX1核心模块环境(Ubuntu18.04)下测试ROS驱动,打开使用RVIZ 查看点云数据,本文的前提条件是你的TX1里已经安装了ROS版本:Melodic。关于测试…

三、k8s资源管理

文章目录1 k8s资源管理介绍2 YAML语言介绍3 资源管理方式3.1 命令式对象管理3.2 命令式对象配置3.3 声明式对象配置3.4 如何编写YAML1 k8s资源管理介绍 在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。 kubernetes的本质…

MySQL字符集和排序规则详解

一. 相关概念1. 字符集MySQL提供了多种字符集和排序规则选择,其中字符集设置和数据存储以及客户端与MySQL实例的交互相关,排序规则和字符串的对比规则相关(1). 字符集的设置可以在MySQL实例、数据库、表、列四个级别(2). MySQL设置字符集支持在InnoDB, M…

Git学习:工作流学习实践

文章目录一、前言二、开发过程一、前言 在实践的项目开发过程中,会使用Git或者类似的版本控制工具来管理代码。下面介绍基于Git工具在实际项目开发过程中的使用流程。 如上图所示显示了项目开发的一个简化流程。在开发一个新需求/版本的时候,一般会从主…

筛法求欧拉函数

欧拉函数的定义 在数论中,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目. 欧拉函数的重要性质 若(即m与n互质),则若为质数,则若为质数,则对于性质2,若为质数,则小于的个数都互质&am…

北大陈斌Python算法笔记(二)

前言 🍀作者简介:被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 🍁个人主页:红中 🍂不就是蓝桥杯嘛,干他!!我堂堂 栈的应用:简单括号匹…

docker安装nginx与容器之间的互相通信

目录 1. docker网络模式 2. 连接容器的三种方法 3. Docker Networking 3.1 创建网络 3.2 查看宿主机中创建的网络 3.3 删除网络 3.4 如何使用网络 4.搭建Nginx 1.准备工作 1.1 拉取镜像 ​编辑1.2 在宿主机中创建挂载目录 2.准备2个tomcat 容器集群 3.准备 Nginx配…

力扣(LeetCode)1658. 将 x 减到 0 的最小操作数(C++/Python)

题目描述 逆向思维滑动窗口 题目分析 : 从数组左侧和右侧,取出左侧的连续数字,右侧的连续数字,使得这些数字之和等于 x,维护最小取数次数,作为答案 。 设整个数组之和 total ,除去左侧和右侧的…

Notes 12.0.2版本新特性

大家好,才是真的好。 随着上周代号多瑙河的Notes/Domino 12.0.2版本正式发布,很多人在周末加班,写新特性和功能测试文档等,恩,我也是这样,所以今天第一时间来介绍下Notes 12.0.2客户机新特性。 从12.0.2版…

GC中的一些技术

OopMap(ordinary object pointer map) 记录时机 JIT编译时在特定的位置(安全点/安全区)记录下OopMap,记录了执行到该方法的某条指令的时候,栈上和寄存器里哪些位置是引用类加载动作完成时,Hot…

关于sql注入这一篇就够了

本文章根据b站迪总课程总结出来,若有不足请见谅 目录 本文章根据b站迪总课程总结出来,若有不足请见谅 存在sql注入条件 判断数据库类型 注入mysql思路 判断网站是否存在注入点 判断列名数量(字段数) 文件读写操作 网站路径获取方法 注入类型 按注入点数据…

Linux物理内存:伙伴系统(buddy system)

引入之前写过一篇文章将伙伴系统,可以参考:内存池算法简介从上面的虚拟机上可以看到,X86系统上,有三个物理内存区,DMA,DMA32,Normal,可以看到阶数为11。struct page {atomic_t _mapc…

J DBC相关

JDBC基础什么是JDBC入门程序功能类工具类SQL注入攻击原理PreparedStatement的介绍数据库连接池原理自定义连接池归还连接JDBC框架自定义JDBC框架JDBC基础 什么是JDBC 用于执行SQL语句的java API,实现不同关系型数据库的连接 入门程序 导入jar包 注册驱动 获取连…

Linux驱动开发基础__gpio子系统重要概念

目录 1 引入 2 在设备树中指定引脚 3 在驱动代码中调用GPIO子系统 4 sysfs 中的访问方法 1 引入 要操作 GPIO 引脚,先把所用引脚配置为 GPIO 功能,这通过 Pinctrl 子系统来实现。 然后就可以根据设置引脚方向(输入还是输出)、读值──获得电平状…

Windows Docker Desktop开放API端口2375用于远程调用

Windows Docker Desktop开放API端口2375用于远程调用问题解决开启IP Helper服务开启Docker配置开放2375端口端口映射找到需要暴露的IP执行端口映射命令Windows防火墙关闭防火墙添加防火墙规则测试问题 Windows Docker Desktop为了安全,默认设置中只有localhost:237…

入门的葡萄酒知识

葡萄酒的分类(根据制造方法) 静态葡萄酒 红葡萄酒 Red Wine,白葡萄酒 White Wine,玫瑰红/桃红/粉红葡萄Rose Wine。 气泡(起泡)葡萄酒 有气泡的葡萄酒,分香槟Champagne及气泡葡萄酒两类。只有在…

Servlet(上)

Servlet组件(上) 学习目标 了解Web资源的概念了解为什么需要Servlet掌握Servlet是什么掌握Servlet的HelloWorld掌握Servlet的执行原理掌握Servlet的生命周期和生命周期方法掌握ServletConfig的使用掌握Servlet的体系结构掌握Servlet的映射路径的编写方式掌握创建Servlet最常用…

机器学习简单介绍

机器学习简介 定义 机器学习是人工智能(AI)和计算机科学的一个分支,专注于使用数据和算法来模仿人类的学习方式,逐步提高其准确性。 简单来说,是一种运用数学公式来对问题进行最优化求解的方法 分类 一般来说将:机器学习分为…

睿联技术在创业板过会:收入依赖摄像机单机,计划募资11亿元

2023年1月6日,深圳证券交易所披露的信息显示,深圳市睿联技术股份有限公司(下称“睿联技术”)获得创业板上市委员会审议通过。据贝多财经了解,睿联技术的上市申请于2022年6月2日获得创业板受理。 本次冲刺创业板上市&am…

Unity 3D 地形系统概述|| Unity 3D 创建地形

在三维游戏世界中,通常会将丰富多彩的游戏元素融合在一起,比如游戏中起伏的地形、郁郁葱葱的树木、蔚蓝的天空、、凶恶的猛兽等,营造出身临其境的游戏沉浸感,让玩家置身游戏世界,忘记现实。 地形作为游戏场景中必不可…