程序员波特的个人博客

一个小而美的程序员编程资料站

0%

如何准备系统设计面试

系统设计在面试中一定是最让面试者头疼的事情之一。因为系统设计相关的问题通常是开放式的,所以没有标准答案。你在和面试官思想的交流碰撞中会慢慢优化自己的系统设计方案。理论上来说,系统设计面试官一起一步一步改进原有系统设计方案的过程。

系统设计题往往也非常能考察岀面试者的综合能力,回答好的话,很易就能在面试中脱颖而岀。不论是对于参加社招还是校招的小伙伴,都很有必要重视起来接下来。

我会带着小伙伴们从我的角度出发来谈谈:如何准备面试中的系统设计

由于文章篇幅有限,就不列举实际例子了,可能会在后面的文章中单独提一些具体的例子

系统设计面试一般怎么问

我简单总下系统设计面试相关问题的问法个

  1. 设计某某系统比如秒杀系统、微博系统、抢红包系统、短网址系统
  2. 设计某某系统中一个功能比如哔哩哔哩点赞功能
  3. 设计一个框架比如RPC框架、消息队列、缓存框架、分布式文件系统等等
  4. 某某系统的技术选型比如缓存用Redis还是Memcached、网关用Spring Cloud Gateway还是Netflix Zuul2

系统设计怎么做?

我们将步骤总结成了以下 4 步。

Step1:问清楚系统具体要求

当面试官给出了系统设计题目之后,一定不要立即开始设计解决方案。 你需要先理解系统设计的需求:功能性需求和非功能性需求。

为了避免自己曲解题目所想要解决的问题,你可以先简要地给面试官说说自己的理解,

为啥要询问清楚系统的功能性需求也就是说系统包含哪些功能呢?

毕竟,如果面试官冷不丁地直接让你设计一个微博系统,你不可能把微博系统涵盖的功能比如推荐信息流、会员机制等一个一个都列举出来,然后再去设计吧!你需要筛选出系统所提供的核心功能(缩小边界范围)!

为啥要询问清楚系统的非功能性需求或者说约束条件比如系统需要达到多少QPS呢?

让你设计一个1w人用的微博系统和100w人用的微博系统能一样么?不同的约束系统对应的系统设计方案肯定是不一样的。

Step2:对系统进行抽象设计

我们需要在一个 High Level 的层面对系统进行设计。

你可以画出系统的抽象架构图,这个抽象架构图中包含了系统的一些组件以及这些组件之间的连接。

imgStep3:考虑系统目前需要优化的点

对系统进行抽象设计之后,你需要思考当前抽象的系统设计有哪些需要优化的点,比如说:

  1. 当前系统部署在一台机器够吗?是否需要部署在多台机器然后进行负载均衡呢?
  2. 数据库处理速度能否支撑业务需求?是否需要给指定字段加索引?是否需要读写分离?是否需要缓存?
  3. 数据量是否大到需要分库分表?
  4. 是否存在安全隐患?
  5. 系统是否需要分布式文件系统?
  6. ……
Step4:优化你的系统抽象设计

根据 Step 3 中的“系统需要优化的点” 对系统的抽象设计做进一步完善。

系统设计该如何准备?

知识储备

系统设计面试非常考察你的知识储备,系统设计能力的提高需要大量的理论知识储备。比如说你要知道大型网站架构设计必备的三板斧:

1.高性能架构设计: 熟悉系统常见性能优化手段比如引入 读写分离、缓存、负载均衡、异步 等等。

**2.高可用架构设计 :**CAP理论和BASE理论、通过集群来提高系统整体稳定性、超时和重试机制、应对接口级故障:降级、熔断、限流、排队。

**3.高扩展架构设计 :**说白了就是懂得如何拆分系统。你按照不同的思路来拆分软件系统,就会得到不同的架构。

实战

虽然懂得了理论,但是自己没有进行实践的话,很多东西是无法体会到的!

因此,你还要不断通过实战项目锻炼自己的系统设计能力

保持好奇心

多思考自己经常浏览的网站是怎么做的。比如:

1你刷微博的时候可以思考一下微博是如何记录点赞数量的?

2你看哔哩哔哩的时候可以思考一下消息提醒系统是如何做的?

3你使用短链系统的时候可以考虑一下短链系统是如何做的?

4……

技术选型

实现同样的功能,一般会有多种技术选择方案,比如缓存用Redis 还是 Memcached、网关用Spring Cloud Gateway还是Netflix Zuul2 。 很多时候,面试官在系统设计面过程中会具体到技术的选型,因而,你需要区分不同技术的优缺点。

系统设计面试必知

系统设计的时候必然离不开描述性能相关的指标比如 QPS。

性能相关的指标
响应时间

响应时间RT(Response-time)就是用户发出请求到用户收到系统处理结果所需要的时间。

RT是一个非常重要且直观的指标,RT数值大小直接反应了系统处理用户请求速度的快慢。

并发数

并发数可以简单理解为系统能够同时供多少人访问使用也就是说系统同时能处理的请求数量。

并发数反应了系统的负载能力。

QPS 和 TPS
  • QPS(Query Per Second) :服务器每秒可以执行的查询次数;

  • TPS(Transaction Per Second) :服务器每秒处理的事务数(这里的一个事务可以理解为客户发出请求到收到服务器的过程);

书中是这样描述 QPS 和 TPS 的区别的。

QPS vs TPS:QPS 基本类似于 TPS,但是不同的是,对于一个页面的一次访问,形成一个TPS;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“QPS”之中。如,访问一个页面会请求服务器2次,一次访问,产生一个“T”,产生2个“Q”。

吞吐量

吞吐量指的是系统单位时间内系统处理的请求数量。

一个系统的吞吐量与请求对系统的资源消耗等紧密关联。请求对系统资源消耗越多,系统吞吐能力越低,反之则越高。

TPS、QPS都是吞吐量的常用量化指标。

  • QPS(TPS) = 并发数/平均响应时间(RT)

  • 并发数 = QPS * 平均响应时间(RT)

系统活跃度

介绍几个描述系统活跃度的常见名词,建议牢牢记住。你不光会在回答系统设计面试题的时候碰到,日常工作中你也会经常碰到这些名词。

PV(Page View)

访问量, 即页面浏览量或点击量,衡量网站用户访问的网页数量;在一定统计周期内用户每打开或刷新一个页面就记录1次,多次打开或刷新同一页面则浏览量累计。UV 从网页打开的数量/刷新的次数的角度来统计的。

UV(Unique Visitor)

独立访客,统计1天内访问某站点的用户数。1天内相同访客多次访问网站,只计算为1个独立访客。UV 是从用户个体的角度来统计的。

DAU(Daily Active User)

日活跃用户数量。

MAU(monthly active users)

月活跃用户人数。

举例:某网站 DAU为 1200w, 用户日均使用时长 1 小时,RT为0.5s,求并发量和QPS。

平均并发量 = DAU(1200w)* 日均使用时长(1 小时,3600秒) /一天的秒数(86400)=1200w/24 = 50w

真实并发量(考虑到某些时间段使用人数比较少) = DAU(1200w)* 日均使用时长(1 小时,3600秒) /一天的秒数-访问量比较小的时间段假设为8小时(57600)=1200w/16 = 75w

峰值并发量 = 平均并发量 * 6 = 300w

QPS = 真实并发量/RT = 75W/0.5=150w/s

常用性能测试工具
后端常用

既然系统设计涉及到系统性能方面的问题,那在面试的时候,面试官就很可能会问:你是如何进行性能测试的?

推荐 4 个比较常用的性能测试工具:

  1. Jmeter :Apache JMeter 是 JAVA 开发的性能测试工具。

  2. LoadRunner:一款商业的性能测试工具。

  3. Galtling :一款基于Scala 开发的高性能服务器性能测试工具。

  4. ab :全称为 Apache Bench 。Apache 旗下的一款测试工具,非常实用。

没记错的话,除了 LoadRunner 其他几款性能测试工具都是开源免费的。

前端常用
  1. Fiddler:抓包工具,它可以修改请求的数据,甚至可以修改服务器返回的数据,功能非常强大,是Web 调试的利器。

  2. HttpWatch: 可用于录制HTTP请求信息的工具。

常见软件的QPS

这里给出的 QPS 仅供参考,实际项目需要进行压测来计算。

  • Nginx :一般情况下,系统的性能瓶颈基本不会是 Nginx。单机 Nginx 可以达到 30w +。

  • Redis: Redis 官方的性能测试报告:https://redis.io/topics/benchmarks 。从报告中,我们可以得出 Redis 的单机 QPS 可以达到 8w+(CPU性能有关系,也和执行的命令也有关系比如执行 SET 命令甚至可以达到10w+QPS)。

  • MySQL: MySQL 单机的 QPS 为 大概在 4k 左右。

  • Tomcat :单机 Tomcat 的QPS 在 2w左右。这个和你的 Tomcat 配置有很大关系,举个例子Tomcat 支持的连接器有 NIO、NIO.2 和 APR。 AprEndpoint 是通过 JNI 调用 APR 本地库而实现非阻塞 I/O 的,性能更好,Tomcat 配置 APR 为 连接器的话,QPS 可以达到 3w左右。更多相关内容可以自行搜索 Tomcat 性能优化。

系统设计原则

合适优于先进 > 演化优于一步到位 > 简单优于复杂

常见的性能优化策略

性能优化之前我们需要对请求经历的各个环节进行分析,排查出可能出现性能瓶颈的地方,定位问题。

下面是一些性能优化时,我经常拿来自问的一些问题:

  1. 当前系统的SQL语句是否存在问题?

  2. 当前系统是否需要升级硬件?

  3. 系统是否需要缓存?

  4. 系统架构本身是不是就有问题?

  5. 系统是否存在死锁的地方?

  6. 数据库索引使用是否合理?

  7. 系统是否存在内存泄漏?(Java 的自动回收内存虽然很方便,但是,有时候代码写的不好真的会造成内存泄漏)

  8. 系统的耗时操作进行了异步处理?

  9. ……

性能优化必知法则

SQL优化,JVM、DB,Tomcat参数调优 > 硬件性能优化(内存升级、CPU核心数增加、机械硬盘—>固态硬盘等等)> 业务逻辑优化/缓存 > 读写分离、集群等 > 分库分表

系统设计面试的注意事项

想好再说

没必要面试官刚问了问题之后,你没准备好就开始回答。这样不会给面试官带来好印象的!系统设计本就需要面试者结合自己的以往的经验进行思考,这个过程是需要花费一些时间的。

没有绝对的答案

系统设计没有标准答案。重要的是你和面试官一起交流的过程。

一般情况下,你会在和面试官的交流过程中,一步一步完成系统设计。这个过程中,你会在面试官的引导下不断完善自己的系统设计方案。

因此,你不必要在系统设计面试之前找很多题目,然后只是单纯记住他们的答案。

勿要绝对

系统设计没有最好的设计方案,只有最合适的设计方案。这就类比架构设计了:软件开发没有银弹,架构设计的目的就是选择合适的解决方案。 何为银弹? 狼人传说中,只有银弹(银质子弹)才能制服这些猛兽。对应到软件开发活动中,银弹特指开发者们寻求的一种克服软件开发这个难缠的猛兽的“万能钥匙🔑”。

权衡利弊

知道使用某个技术可能会为系统带来的利弊。比如使用消息队列的好处是解耦和削峰,但是,同样也让系统可用性降低、复杂性提高,同时还会存在一致性问题(消息丢失或者消息未被消费咋办)。

慢慢优化

刚开始设计的系统不需要太完美,可以慢慢优化。

不追新技术

使用稳定的、适合业务的技术,不必要过于追求新技术。

追简避杂

系统设计应当追求简单避免复杂。KISS( Keep It Simple, Stupid)原则——保持简单,易于理解。

总结

这篇文章简单带着小伙伴们分析了一下系统设计面试。如果你还想要深入学习的话,可以参考: https://github.com/donnemartin/system-design-primer

如何设计一个秒杀系统

今天这篇文章咱们就开始从后端的角度来谈谈:“如何设计秒杀系统?”。

在你看这篇文章之前,我想说的是系统设计没有一个标准答案,你需要结合自己的过往经验来回答,我这篇文章也是简单说说自己的看法。

下面是正文!

设计秒杀系统之前,我们首先需要对秒杀系统有一个清晰的认识。

秒杀系统主要为商品(往往是爆款商品)秒杀活动提供支持,这个秒杀活动会限制商品的个数以及秒杀持续时间。

img

为什么秒杀系统的设计是一个难点呢? 是因为它的业务复杂么? 当然不是!

秒杀系统的业务逻辑非常简单,一般就是下订单减库存,难点在于我们如何保障秒杀能够顺利进行。

img

  • 秒杀开始的时候,会有大量用户同时参与进来,因此秒杀系统一定要满足 高并发 和 高性能 。
  • 为了保证秒杀整个流程的顺利进行,整个秒杀系统必须要满足 高可用 。
  • 除此之外,由于商品的库存有限,在面对大量订单的情况下,一定不能超卖,我们还需要保证 一致性 。

很多小伙伴可能不太了解当代三高互联网架构:高并发、高性能、高可用。

我这里简单解释一下:高并发简单来说就是能够同时处理很多用户请求。高性能简单来说就是处理用户的请求速度要快。高可用简单来说就是我们的系统要在趋近 100% 的时间内都能正确提供服务。

知道了秒杀系统的特点之后,我们站在技术层面来思考一下:“设计秒杀系统的过程中需要重点关注哪些问题”。

  1. 参与秒杀的商品属于热点数据,我们该如何处理热点数据?
  2. 商品的库存有限,在面对大量订单的情况下,如何解决超卖的问题?
  3. 如果系统用了消息队列,如何保证消息队列不丢失消息?
  4. 如何保证秒杀系统的高可用?
  5. 如何对项目进行压测?有哪些工具?
  6. ……

好的,废话不多说!正式开始!

高并发&高性能

热点数据处理

何为热点数据? 热点数据指的就是某一时间段内被大量访问的数据,比如爆款商品的数据、新闻热点。

为什么要关注热点数据? 热点数据可能仅仅占据系统所有数据的 0.1% ,但是其访问量可能是比其他所有数据之和还要多。不重点处理热点数据,势必会给系统资源消耗带来严峻的挑战。

热点数据的分类? 根据热点数据的特点,我们通常将其分为两类:

  • 静态热点数据 :可以提前预测到的热点数据比如要秒杀的商品。

  • 动态热点数据 : 不能够提前预测到的热点数据,需要通过一些手段动态检测系统运行情况产生。

另外,处理热点数据的问题的关键就在于 我们如何找到这些热点数据(或者说热 key),然后将它们存在 jvm 内存里。 对于并发量非常一般的系统直接将热点数据存放进缓存比如 Redis 中就可以了,不过像淘宝、京东这种级别的并发量,如果把某些热点数据放在 Redis 中,直接可能就将整个 Redis 集群给干掉了。

如何检测热点数据?

我了解到的是市面上也有一些类似的中间件,比如京东零售的 hotkey 就是一款专门用于检测热点数据的中间件,它可以毫秒级探测热点数据,毫秒级推送至服务器集群内存。相关阅读:京东毫秒级热 key 探测框架设计与实践,已完美支撑 618 大促

另外,我们平时使用 Redis 做缓存比较多,关于如何快速定位 Redis 热点数据,可以看下如何快速定位 Redis 热 key这篇文章。

img

如何处理热点数据? 热点数据一定要放在缓存中,并且最好可以写入到 jvm 内存一份(多级缓存),并设置个过期时间。需要注意写入到 jvm 的热点数据不宜过多,避免内存占用过大,一定要设置到淘汰策略。

为什么还要放在 jvm 内存一份? 因为放在 jvm 内存中的数据访问速度是最快的,不存在什么网络开销。

流量削峰

消息队列

秒杀开始之后的流量不是很大,我处理不了嘛!那我就先把这些请求放到消息队列中去。然后,咱后端服务再慢慢根据自己的能力去消费这些消息,这样就避免直接把后端服务打垮掉。

img

消息队列是一种非常实用的流量削峰手段。只要是涉及到流量削峰,那必然不可缺少消息队列。

回答问题/验证码

我们可以在用户发起秒杀请求之前让其进行答题或者输入验证码。

这种方式一方面可以避免用户请求过于集中,另一方面可以有效解决用户使用脚本作弊。

回答问题/验证码这一步建议除了对答案的正确性做校验,还需要对用户的提交时间做校验,比如提交时间过短(<1s)的话,大概就是使用脚本来处理的。

高可用

集群化

如果我们想要保证系统中某一个组件的高可用,往往需要搭建集群来避免单点风险,比如说 Nginx 集群、Kafka 集群、Redis 集群。

我们拿 Redis 来举例说明。如果我们需要保证 Redis 高可用的话,该怎么做呢?

你直接通过 Redis replication(异步复制) 搞个一主(master)多从(slave)来提高可用性和读吞吐量,slave 的多少取决于你的读吞吐量。

img

这样的方式有一个问题:一旦 master 宕机,slave 晋升成 master,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。

不过,这个问题我们可以通过 Sentinel(哨兵) 来解决。Redis Sentinel 是 Redis 官方推荐的高可用性(HA)解决方案。

Sentinel 是 Redis 的一种运行模式 ,它主要的作用就是对 Redis 运行节点进行监控。当 master 节点出现故障的时候, Sentinel 会帮助我们实现故障转移,确保整个 Redis 系统的可用性。整个过程完全自动,不需要人工介入!

img

Sentinel 也是一个 Redis 进程,只是不对外提供读写服务,通常哨兵要配置成单数。

限流

限流是从用户访问压力的角度来考虑如何应对系统故障。限流为了对服务端的接口接受请求的频率进行限制,防止服务挂掉。

🌰 举个例子:我们的秒杀接口一秒只能处理 10w 个请求,结果秒杀活动刚开始一下子来了 15w 个请求。这肯定不行啊!我们只能通过限流把 5w 个请求给拦截住,不然系统直接就给整挂掉了!

限流的话可以直接用 Redis 来做(建议基于 Lua 脚本),也可以使用现成的流量控制组件比如 Sentinel 、Hystrix 、Resilience4J 。

Hystrix 是 Netflix 开源的熔断降级组件。

Sentinel 是阿里巴巴体提供的面向分布式服务架构的流量控制组件,经历了淘宝近10年双11(11.11)购物节的所有核心场景(比如秒杀活动)的考验。

Sentinel 主要以流量为切入点,提供 流量控制、熔断降级、系统自适应保护等功能来保护系统的稳定性和可用性。

个人比较建议使用 Sentinel ,更新维护频率更高,功能更强大,并且生态也更丰富(Sentinel 提供与 Spring Cloud、Dubbo 和 gRPC 等常用框架和库的开箱即用集成, Sentinel 未来还会对更多常用框架进行适配,并且会为 Service Mesh 提供集群流量防护的能力)。

img

排队

你可以把排队看作是限流的一个变种。限流是直接拒绝了用户的请求,而排队则是让用户等待一定的时间(类比现实世界的排队)。

排队虽然没有直接拒绝用户,但用户等了很长时间后进入系统,体验并不一定比限流好。

🌰 举个例子:当请求量达到一个阈值的时候,我们就通知用户让它们排队。等到系统可以继续处理请求之后,再慢慢来处理。

降级

降级是从系统功能优先级的角度考虑如何应对系统故障。

服务降级指的是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级的核心思想就是丢车保帅,优先保证核心业务。例

🌰 举个例子:当请求量达到一个阈值的时候,我们对系统中一些非核心的功能直接关闭或者让它们功能降低。这样的话,系统就有更多的资源留给秒杀功能了!

熔断

熔断和降级是两个比较容易混淆的概念,两者的含义并不相同。降级的目的在于应对系统自身的故障,而熔断的目的在于应对当前系统依赖的外部系统或者第三方系统的故障。

熔断可以防止因为秒杀交易影响到其他正常服务的提供

🌰 举个例子: 秒杀功能位于服务 A 上,服务 A 上同时还有其他的一些功能比如商品管理。如果服务 A 上的商品管理接口响应非常慢的话,其他服务直接不再请求服务 A 上的商品管理这个接口,从而有效避免其他服务被拖慢甚至拖死。

一致性

减库存方案

常见的减库存方案有:

  • 下单即减库存 :只要用户下单了,即使不付款,我们就扣库存。

  • 付款再减库存 :当用户付款了之后,我们在减库存。不过, 这种情况可能会造成用户下订单成功,但是付款失败。

一般情况下都是 下单减扣库存 ,像现在的购物网站比如京东都是这样来做的。

不过,我们还会对业务逻辑做进一步优化,比如说对超过一定时间不付款的订单特殊处理,释放库存。

对应到代码层面,我们应该如何保证不会超卖呢?

我们上面也说,我们一般会提前将秒杀商品的信息放到缓存中去。我们可以通过 Redis 对库存进行原子操作。伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 第一步:先检查 库存是否充足
Integer stockNum = (Integer)redisTemplate.get(key);
if(stockNum<1){
...
}
// 第二步:如果库存充足,减少库存(假设只能购买一件)
Long count = redisTemplate.increment(key,-1);
if(count>=0){
...
}else{
...
}

你也可以通过 Lua 脚本来减少多个命令的网络开销并保证多个命令整体的原子性。伪代码如下:

1
2
3
4
5
6
7
8
9
-- 第一步:先检查 库存是否充足,库存不足,返回0
local stockNum=tonumber(redis.call("get",key));
if stockNum<1 then
return 0;
-- 第二部:如果库存充足,减少库存(假设只能购买一件),返回1
else
redis.call('DECRBY',key,1);
return 1;
end
接口幂等

什么是幂等呢? 在分布式系统中,幂等(idempotency)是对请求操作结果的一个描述,这个描述就是不论执行多少次相同的请求,产生的效果和返回的结果都和发出单个请求是一样的。

🌰 举个例子:假如咱们的前后端没有保证接口幂等性,我作为用户在秒杀商品的时候,我同时点击了多次秒杀商品按钮,后端处理了多次相同的订单请求,结果导致一个人秒杀了多个商品。这个肯定是不能出现的,属于非常严重的 bug 了!

保证分布式接口的幂等性对于数据的一致性至关重要,特别是像支付这种涉及到钱的接口。保证幂等性这个操作并不是说前端做了就可以的,后端同样要做。

前端保证幂等性的话比较简单,一般通过当用户提交请求后将按钮致灰来做到。后端保证幂等性就稍微麻烦一点,方法也是有很多种,比如:

  1. 同步锁;

  2. 分布式锁;

  3. 业务字段的唯一索性约束,防止重复数据产生。

  4. ……

拿分布式锁来说,我们通过加锁的方式限制用户在第一次请求未结束之前,无法进行第二次请求。

分布式锁一般基于 Redis 来做比较多一些,这也是我比较推荐的一种方式。另外,如果使用 Redis 来实现分布式锁的话,比较推荐基于 Redisson。相关阅读:分布式锁中的王者方案 - Redisson

1
2
3
4
5
6
7
8
// 1.设置分布式锁
RLock lock = redisson.getLock("lock");
// 2.占用锁
lock.lock();
// 3.执行业务
...
// 4.释放锁
lock.unlock();

当然了,除了 Redis 之外,像 ZooKeeper 等中间也可以拿来做分布式锁。

性能测试

上线之前压力测试是必不可少的。推荐 4 个比较常用的性能测试工具:

  1. **Jmeter :**Apache JMeter 是 JAVA 开发的性能测试工具。
  2. **LoadRunner:**一款商业的性能测试工具。
  3. **Galtling :**一款基于 Scala 开发的高性能服务器性能测试工具。
  4. **ab :**全称为 Apache Bench 。Apache 旗下的一款测试工具,非常实用。

没记错的话,除了 LoadRunner 其他几款性能测试工具都是开源免费的。

总结

我简单画了一张图来总结一下上面涉及到的一些技术。

img

另外,上面涉及到知识点还蛮多的,如果面试官单独挑出一个来深挖还是能够问出很多问题的。

比如面试官想在消息队里上进行深挖,可能会问:

  • 常见消息队列的对比
  • 如何保证消息的消费顺序?
  • 如何保证消息不丢失?
  • 如何保证消息不重复消费?
  • 如何设计一个消息队列?
  • ……

再比如面试官想在 Redis 上深挖的话,可能会问:

  • Redis 常用的数据结构了解么?
  • Redis 如何保证数据不丢失?
  • Redis 内存占用过大导致响应速度变慢怎么解决?
  • 缓存穿透、缓存雪崩了解么?怎么解决?
  • ……

因此,要想要真正搞懂秒杀系统的设计,你还需要将其涉及到的一些技术给研究透!