查看原文
其他

【硬核】面试官问:你参与的项目有什么亮点?怎么回答。。。

点击关注 👉 微观技术 2022-11-10

大家好,我是Tom哥~


面试官拿到我们的简历,一般会关注两块内容,一块是专业技能,另一块是项目经历。

简单的个人介绍后,一般会先问些偏基础的技术问题,热热身。当然也有很多面试官上来就顺着项目问。根据你介绍项目的过程细节,穿插设置一系列的技术问题。

面试官一般会关注一些有挑战性的方案设计、解决了什么复杂难题,简单一句话,就是你的项目一定要有亮点。

那么,什么是亮点?我们的项目如何积累这些亮点?

下面我们会介绍项目中一些高频亮点设计,我们平时做项目,设计技术方案时也可以多用用,积累些实战经验 。




面对复杂业务,架构设计有什么通用思路?

答案:业务理解转化能力、思维抽象能力、软件建模能力、高并发、高性能、高可用的分布式系统架构设计能力。


谈谈对 DDD 的理解?

答案:通过实体、值对象、聚合根、领域服务、领域对象、限界上下文、资源库,指导微服务落地,将一个大的复杂业务域拆分成若干业务子域。定义领域模型(包含数据、行为),相似业务聚合。


画下项目的业务架构图?

答案:要对简历的项目非常熟悉,不只是自己负责的那部分,观整体通细节。

很多同学面试前没有系统化梳理,面试时现组织语言,给人感觉思路凌乱、条理不够清晰。

面试前可以先自己画画系统架构,理清其中的依赖关系。同时,提炼核心有挑战的技术难点,面试时,重点介绍其来龙去脉。


项目中用过哪些设计模式?

答案:工厂、装饰、克隆、代理、适配器、观察者、策略、模板、单例、责任链、门面等23种软件设计模式,这是软件开发的基本功,每一种设计模式都要非常熟悉。否则很难写出扩展性很高的代码。

之前写过三篇文章,每一种模式都有详细介绍:


如何提升系统的吞吐量?

答案:围绕系统的 “三高原则”,高并发、高性能、高可用,三个方向展开。


面对海量数据,什么是水平拆分、垂直拆分?

答案:

1、垂直拆分可以分为业务维度、技术维度。

  • 业务维度:结合DDD领域驱动设计,将一个大的业务域拆分为若干业务子域,比如电商可以拆分为商户、商品、库存、权限、会员、营销、交易、支付、履约、订单、结算、仓储、物流、财务等。
  • 技术维度:将一个有很多字段的表,按字段的大小、使用频率等特点,拆分为多张表。

2、水平拆分

由于单台机器的性能有限,无法支撑海量数据存储。我们引入逻辑表概念,采用集群模式,将一张逻辑表拆分成多张物理表分散存储在不同服务器,通过分表键路由,比如:时间区域用户id等。

特点:虽然有多张表,但每张表的表结构都是一样的,区别是数据不一样。所有表的数据合并起来才是这个业务表的完整数据。

画外音:数据量大,就分表;并发高,就分库

更多内容,参考  单台 MySQL 支撑不了这么多的并发请求,我们该怎么办?


分库分表时,全局性主键ID有哪些生成方案?

答案:

1、UUID,生成的是 32 位的字符串,虽然可以做到全局唯一性,但我们一般推荐使用整型。

2、SNOWFLAKE,雪花算法,生成一个 64 位的Long类型数据。组成结构:正数位(占1位)+ 时间戳(占41位)+ 工作机器id(10位)+ 序列号部分(12位)

3、数据库号段模式,对不同的业务类型定义初始值和步长,业务系统引入SDK,本地缓存预申请一定数据量的主键ID值,满足一定的并发要求。

4、TinyID,滴滴的开源框架

5、Redis 的 incr 命令

6、Leaf,美团的开源框架

7、Uidgenerator,百度的开源框架


不停机情况下,数据库扩容要怎么做?

答案:

1、首先,创建好新库,应用端修改代码,采用双写机制,将数据也同步一份到新库中

2、数据迁移,将老库中的数据迁移到新库中

3、对新老数据库做数据核对,对不一致的数据做定向同步

4、开关打开,读操作切换到新库,通过线上真实流量验证数据的准确性。

5、经过一段时间的线上验证后,如果没问题,将老库的写操作下线


缓存更新常用策略?

答案:

  • Cache aside,通常会先更新数据库,然后再删除缓存,为了兜底还会设置缓存时间。
  • Read/Write through, 一般是由一个 Cache Provider 对外提供读写操作,应用程序不用感知操作的是缓存还是数据库。
  • Write behind,延迟写入,Cache Provider 每隔一段时间会批量写入数据库,大大提升写的效率。像操作系统的page cache也是类似机制。


写操作时,缓存和数据库如何保持一致性?

答案:常见的方案有以下几个

1、先更新数据库,再更新缓存。

由于是两个操作,如果多线程并发情况下,很难保证线程之间的顺序,可能导致缓存的是旧数据。一般不推荐这种方案

2、先删除缓存,再更新数据库

两个操作,如果中间执行过程中,缓存被删除,恰好有其他线程来读数据,缓存会被重新预热旧的数据。一般不推荐这种方案

3、先更新数据库,再删缓存。

可能会导致无效删除,但是删除本身具有幂等性。该方案成本最低,一般推荐该方案

4、借助消息中间件,对缓存的数据强制维护,但也只能保证最终一致性。

5、不管最终采用哪种方案,Key都要设置一个过期时间,借助自身的淘汰机制保证数据的更新。


如何减少接口的响应时间?

答案:

  • 1、减少接口的处理内容,将非核心逻辑移除,采用MQ解耦,异步化处理。
  • 2、接口内部引入本地缓存和分布式缓存,提升数据加载速度
  • 3、引入池化技术(线程池、进程池、对象池、内存池、连接池、协程池)


事务有哪些特性?

答案:

1、原子性(Atomicity),原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。

2、持久性(Durability),事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

3、一致性(Consistency),事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

4、隔离性(Isolation),一个事务不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。


分布式事务,有哪些解决方案?

答案:

1、执行业务逻辑前,先插入流水任务,如果中间过程调用外部RPC接口服务或者本地数据库操作失败时,流水任务会被定时调度任务周期性触发、重试,直到成功。前提条件,所有接口服务都要实现幂等。当执行成功时,流水记录会被删除。

2、基于事务消息,能保证本地数据库一定成功,其他业务系统做为订阅方,通过重试机制保证最终一致性,但要注意接口幂等。

3、两阶段提交

4、引入业务状态机,初始为 init 状态(对外不可见),待所有依赖的RPC接口全部调用一遍,待所有接口的数据全部初始化,然后开始第二轮调用,将状态置为对外可见。当然,此阶段可能会部分调用失败,需要多次重试

5、TCC 模式。Try:尝试待执行的业务;Confirm:执行业务;Cancel:回滚执行的业务

6、Seata 阿里开源框架,把分布式事务定义为由若干本地事务(分支)组成的全局事务。被全局事务管理的全部分支,将在协调器的协调下,保证一起成功或一起回滚。

上面列举的方案细节,可以查看 如何解决分布式事务


如何预防死锁?

答案:互斥条件、请求和保持条件、环路等待、不可剥夺。只要打破其他一个条件即可。


什么是乐观锁?什么是悲观锁?

答案:

  • 乐观锁:分为三个阶段:数据读取、写入校验、数据写入。在数据进行提交更新时,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回错误信息,让用户决定如何去做,fail-fast机制。
  • 悲观锁:对数据的修改持保守态度,在整个数据处理过程中,将数据处于锁定状态,期间其他用户长时间无法访问,影响程序的并发访问性。


常见的限流策略有哪些?

答案:


接口幂等性,有哪些方案?

答案:Select 查询天然支持幂等,而写操作 多次执行可能会导致数据错误,下面简单列举常见的解决方案:

  • insert、update 之前,先select 查询校验
  • 表中加唯一约束
  • 加悲观锁 , select * from order where order_id= 100000 for update; 对操作行锁定。
  • 加乐观锁,表中增加一个attribute_cc自增字段,借助CAS机制控制并发
  • 有些表不适合添加唯一约束,可以单独建一张防重表,在防重表插入成功,在操作其它业务表
  • 引入状态机, update order set status = "wait_seller_send_good" where id=1 and status = "wait_buyer_pay";
  • 采用 分布式锁,第一次请求可以成功加锁,后续请求加锁失败,认为是重复请求。
  • token机制,client 首先请求获取token,提交时除了业务参数外还要带上这个token,server端会对这个token核销,只能核销一次。如果 server 查询不到token,则认为是重复请求。


定时任务,有哪些实现方案?

  • Time,JDK自带的定时器类,与 TimerTask 一起配合使用
  • ScheduledExecutorService,位于java.util.concurrent并发包下,基于多线程。
  • spring task,通过 @Scheduled 注解定义定时规则
  • quartz,开源框架
  • xxl-job,大众点评开源的一个分布式任务调度平台
  • elastic-job,当当网开源的弹性分布式任务调度系统,采用zookeeper实现分布式协调,实现任务高可用以及分片,适用于高并发等复杂业务场景。


经历过的项目,有没有遇到过什么线上问题?

答案:结合自己的工作经历来讲,一个程序员肯定都经历过线上救火的场景。那么找些有技术难度的整理下,如:

  • 没有正确使用Redis的结构,缓存对象的粒度较大,高并发流量导致带宽不足,网络拥堵,连接无法及时释放,客户端报获取连接超时,进而引发整个系统的雪崩。
  • Pulsar系统告警,消息堆积。经排查,某个业务需求改动,SQl没有命中索引,导致接口处理时间增加数倍,从而降低了消费速度,进而消息堆积。
  • 线上系统报OOM问题、内存泄露问题

以上,只是个举个例子。不同的业务,不同的系统,不同的人,经历的线上问题也千奇百怪,可以多收集些。




关于我:前阿里P7技术专家,出过专利,竞赛拿过奖,CSDN博客专家,负责过电商交易、社区生鲜、互联网金融等业务,多年团队管理经验。

关注公众号「微观技术」,后台回复 “算法” ,免费领取资料



推荐阅读

团队管理那点破事!OKR绩效、核心人才、面试、技术分享、研发流程....

中台不是万能药!

Redis缓存那点破事 | 绝杀面试官 25 问!

MYSQL 那点破事!索引、SQL调优、事务、B+树、分表 ....

TCP网络那点破事!三次握手、四次挥手、TIME-WAIT ....



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存