技术与架构设计面试目录纲领

228 阅读10分钟

💨 作者:laker,因为喜欢LOL滴神faker,又是NBA湖人队🏀(laker)粉丝儿(主要是老詹的粉丝儿),本人又姓,故取笔名:laker
❤️喜欢分享自己工作中遇到的问题和解决方案以及一些读书笔记和心得分享
🌰本人创建了微信公众号【Java大厂面试官】,用于和大家交流分享
🏰 个人微信【lakernote】,加作者备注下暗号:cv之道


文章目录

技术与架构设计面试

微服务

高可用系统设计

使用集群,减少单点故障

先拿常用的 Redis 举个例子!我们如何保证我们的 Redis 缓存高可用呢?答案就是使用集群,避免单点故障。当我们使用一个 Redis 实例作为缓存的时候,这个 Redis 实例挂了之后,整个缓存服务可能就挂了。使用了集群之后,即使一台 Redis 实例,不到一秒就会有另外一台 Redis 实例顶上。

限流

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。——来自 alibaba-Sentinel 的 wiki。

超时和重试机制设置

一旦用户请求超过某个时间的得不到响应,就抛出异常。这个是非常重要的,很多线上系统故障都是因为没有进行超时设置或者超时设置的方式不对导致的。我们在读取第三方服务的时候,尤其适合设置超时和重试机制。一般我们使用一些 RPC 框架的时候,这些框架都自带的超时重试的配置。如果不进行超时设置可能会导致请求响应速度慢,甚至导致请求堆积进而让系统无法在处理请求。重试的次数一般设为 3 次,再多次的重试没有好处,反而会加重服务器压力(部分场景使用失败重试机制会不太适合)。

熔断机制

超时和重试机制设置之外,熔断机制也是很重要的。 熔断机制说的是系统自动收集所依赖服务的资源使用情况和性能指标,当所依赖的服务恶化或者调用失败次数达到某个阈值的时候就迅速失败,让当前系统立即切换依赖其他备用服务。 比较常用的是流量控制和熔断降级框架是 Netflix 的 Hystrix 和 alibaba 的 Sentinel。

异步调用

异步调用的话我们不需要关心最后的结果,这样我们就可以用户请求完成之后就立即返回结果,具体处理我们可以后续再做,秒杀场景用这个还是蛮多的。但是,使用异步之后我们可能需要 适当修改业务流程进行配合,比如用户在提交订单之后,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功。除了可以在程序中实现异步之外,我们常常还使用消息队列,消息队列可以通过异步处理提高系统性能(削峰、减少响应所需时间)并且可以降低系统耦合性。

使用缓存

如果我们的系统属于并发量比较高的话,如果我们单纯使用数据库的话,当大量请求直接落到数据库可能数据库就会直接挂掉。使用缓存缓存热点数据,因为缓存存储在内存中,所以速度相当地快!

高并发系统设计

系统拆分

将一个系统拆分为多个子系统,用 dubbo 来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,不也可以扛高并发么。

用户服务、库存服务、地址服务、商品服务、购物车服务、订单服务、公共文件。

缓存

缓存,必须得用缓存。大部分的高并发场景,都是读多写少,那你完全可以在数据库和缓存里都写一份,然后读的时候大量走缓存不就得了。毕竟人家 redis 轻轻松松单机几万的并发。所以你可以考虑考虑你的项目里,那些承载主要请求的读场景,怎么用缓存来抗高并发。

Redis和guava。

MQ

MQ,必须得用 MQ。可能你还是会出现高并发写的场景,比如说一个业务操作里要频繁搞数据库几十次,增删改增删改,疯了。那高并发绝对搞挂你的系统,你要是用 redis 来承载写那肯定不行,人家是缓存,数据随时就被 LRU 了,数据格式还无比简单,没有事务支持。所以该用 mysql 还得用 mysql 啊。那你咋办?用 MQ 吧,大量的写请求灌入 MQ 里,排队慢慢玩儿,后边系统消费后慢慢写,控制在 mysql 承载范围之内。所以你得考虑考虑你的项目里,那些承载复杂写业务逻辑的场景里,如何用 MQ 来异步写,提升并发性。MQ 单机抗几万并发也是 ok 的,这个之前还特意说过。

Redis的队列作消息队列。

分库分表

分库分表,可能到了最后数据库层面还是免不了抗高并发的要求,好吧,那么就将一个数据库拆分为多个库,多个库来扛更高的并发;然后将一个表拆分为多个表,每个表的数据量保持少一点,提高 sql 跑的性能。

购物车表、订单表、评论表。

读写分离

读写分离,这个就是说大部分时候数据库可能也是读多写少,没必要所有请求都集中在一个库上吧,可以搞个主从架构,主库写入,从库读取,搞一个读写分离。读流量太多的时候,还可以加更多的从库。

mycat读写分离。

ElasticSearch

Elasticsearch,简称 es。es 是分布式的,可以随便扩容,分布式天然就可以支撑高并发,因为动不动就可以扩容加机器来扛更高的并发。那么一些比较简单的查询、统计类的操作,可以考虑用 es 来承载,还有一些全文搜索类的操作,也可以考虑用 es 来承载。

搜索商品、电商必备。

高并发原则

  • 无状态:应用无状态,配置文件有状态
  • 拆分:系统维度、功能维度、读写维度、AOP维度、模块维度
  • 服务化:进程内服务->单机远程服务->集群手动注册服务->自动注册和发现服务->服务分组/隔离/路由->服务治理(限流/黑名单)
  • 消息队列:实现服务解耦、异步处理、流量削峰/缓冲(需要注意:处理生产消息失败、消息重复接收处理、生产重试;作为大流量缓冲,牺牲强一致性,保证最终一致性;需要数据校对)
  • 数据异构:异构数据形成闭环,数据存储到合适的存储引擎;聚合数据,使前端通过少量调用拿到所需数据;依赖系统出问题,还能正常工作
  • 缓存:1、浏览器缓存(时效性不强的数据)2、APP客户端缓存(大促前提前下发素材到客户端)3、CDN缓存(把资源推送到离用户最近的CDN节点)4、接入层缓存(没有CDN缓存可以考虑使用Nginx搭建一层接入层)5、应用层缓存(在应用所在机器上部署一组Redis,直接本机读取数据,多机之间主从同步数据)6、分布式缓存(数据量太多,单机存储不了,用分片机制分散流量到多台要,或用分布式缓存实现,常见的分片规则:一致性哈希算法)
  • 并发化

高可用原则

  • 降级:开关集中化管理,推送机制把开关推送到各个应用;可降级的多级读服务;开关前置化;业务降级,高并发流量来袭,保障核心业务,保证数据最终一致性即可,可同步改异步,优先处理高优先级数据
  • 限流:恶意请求只到Cache层;对于穿透到后端的流量考虑Nginx的limit模块;对恶意IP可用Nginx deny屏蔽
  • 切流量:可用Nginx切换故障的应用层
  • 可回滚:版本化(事务回滚、代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚)

业务设计原则

  • 防重设计:防重key、防重表、记录重复日志后续处理
  • 幂等设计:业务系统重复消息消费幂等处理;第三方支付异步回调幂等处理
  • 流程可定义
  • 状态与状态机:状态设计有状态轨迹·,方便追溯;并发状态修改问题;状态变更有序问题;状态变更消息先到后到问题
  • 系统后台操作可反馈
  • 系统后台审批化
  • 文档和注释
  • 备份:代码库、多版本、人员备份

链接:www.jianshu.com/p/39e748801…

总结

遇到架构设计问题,思路如下:

  • 是什么

  • 为什么

  • 怎么实现(先满足功能性需求,再去扩展解决“3高”中的痛点,一般情况下,不会实现“3高”所有,这也很难互相矛盾的,一般都是高可用+高扩展)

    • 1.梳理清楚功能性需求和非功能性需求,注意事项
    • 2.容量估算和评估
    • 3.Api设计
    • 4.数据库设计

重点:分析系统的主要痛点或者复杂度,去解决它即可
例如:
短链接架构,痛点:

  • 短链算法
  • 重定向301,302的选择等

非功能性需求

实现功能性基础上,再考虑下面的。

  • 考虑高可用

    • 数据冗余复制
  • 考虑高性能

    • 数据扩展分片
    • 缓存
    • 负载均衡
  • 考虑扩展性

    • 历史数据清除
  • 考虑安全性

    • 权限

🍎QQ群【837324215】
🍎关注我的公众号【Java大厂面试官】,一起学习呗🍎🍎🍎