1.面试官:Kafka 百万消息积压如何处理?
2.面试官:最多一次、至少一次和正好一次有什么区别?
3.面试官:你项目是怎么存密码的?
4.面试官:如何设计一个分布式ID?
5.面试官:单点登录是怎么工作的?
6.面试官:如何设计安全的对外 API?
7.面试官:如果你的项目要支持百万用户,你会如何设计?
8.面试官:如果你的项目用户规模放大了 100 倍,怎么应对?
9.面试官:你的项目如何做到高可用、高吞吐、高扩展性?
10.面试官:CPU 100% 问题怎么排查?
1.面试官:Kafka 百万消息积压如何处理?
当 Kafka 出现百万级消息积压时,可以从以下几个方面处理:
定位问题:
先检查消费组的 Lag(消息积压量),确认是消费者处理能力不足,还是生产端消息量过大导致的。
提升消费能力:
增加消费者实例数: 增加消费者实例来分摊压力,但确保实例数不超过分区数。
优化消费逻辑: 使用批量拉取和异步处理,减少单条消息的处理时间。
跳过无关消息(如果业务允许): 临时将 offset 调整到最新位置,优先处理新消息。
优化 Kafka 配置:
调整消费端参数,比如增大 max.poll.records 和 fetch.max.bytes,提高拉取效率。
如果 Broker 性能不足,可以扩容集群或增加分区,将负载分散。
控制生产速度:
对生产端限流,避免消息积压进一步恶化。
清理积压消息(最后手段):
如果消息已经过期或无用,可以调整 offset 或删除积压消息。
总结: 处理积压关键在于快速提升消费能力,并结合优化生产消费的配置,确保系统及时恢复正常运行。
2.面试官:最多一次、至少一次和正好一次有什么区别?
“最多一次”、“至少一次”和“正好一次”是分布式系统中常见的消息投递语义,用来描述消息在网络中被传递的行为方式。
企业在设计分布式系统时,通常根据业务需求选择:
最多一次: 低成本,高吞吐,对可靠性要求低的场景。(投递一次,甚至不投递)
至少一次: 适合高可靠性需求,允许通过逻辑处理重复消息。(至少投递一次,甚至更多)
正好一次: 适用于对准确性要求极高的关键业务。(投且投递一次)
3.面试官:你项目是怎么存密码的?
采用 bcrypt/Argon2 哈希密码存储,结合随机盐值确保唯一性,并使用 HTTPS 加密传输。
4.面试官:如何设计一个分布式ID?
设计分布式 ID 时需要权衡:
场景需求: 是否需要有序性、分布式部署、抗单点故障。性能要求: 每秒生成量是否满足高并发需求。
企业一般会根据具体场景选用合适的方案,如雪花算法解决高性能问题,号段模式减少数据库压力,Redis 保证灵活性。
一、为什么分布式 ID 是一个重要问题?
唯一性:
在分布式系统中,多个服务实例和数据库节点需要生成全局唯一的 ID,避免数据冲突。
例如,订单号、用户 ID 等不能重复。
高性能:
分布式 ID 的生成需要满足高并发场景,比如每秒生成百万级 ID。
有序性:
一些场景需要生成的 ID 具有顺序性(如时间递增),方便排序和索引优化。
可扩展性:
系统需要支持节点动态扩展或收缩,ID 生成机制不能成为瓶颈。
二、如何设计一个分布式 ID?
常见的分布式 ID 设计方案如下:
1. 数据库自增 ID
利用数据库的自增字段生成唯一 ID。
优点: 简单易用,ID 有序。
缺点: 性能瓶颈(高并发下会锁表),数据库故障导致不可用。
2. UUID(Universally Unique Identifier)
直接调用系统提供的 UUID 生成方法。
优点: 易实现,生成快,ID 唯一。
缺点: 长度较长(128 位),不适合索引,缺乏有序性。
3. 号段模式(Segment Model)
从数据库中预分配一批连续的 ID 号段(如[1-1000]),每个节点使用自己的号段。
优点: 高效、减少数据库压力。
缺点: 数据库依赖,批量失效可能浪费号段。
4. 雪花算法(Snowflake Algorithm)
Twitter 提出的分布式 ID 生成方案,将 ID 拆分成以下部分:
时间戳(41 位): 毫秒级时间,表示当前时间。
数据中心 ID(5 位)+ 机器 ID(5 位): 标识生成 ID 的节点。
序列号(12 位): 每毫秒内生成的序号,防止重复。
优点: 高性能、低延迟、时间有序、去中心化。
缺点: 实现复杂,需要全局时钟同步。
5. 基于 Redis 的分布式 ID
使用 Redis 的自增操作(INCR)生成 ID。
优点: 高性能,Redis 天生支持分布式。
缺点: Redis 故障会影响 ID 生成。
6. Zookeeper 分布式 ID
利用 Zookeeper 的顺序节点生成全局唯一的 ID。
优点: 可靠性高,ID 有序。
缺点: 性能一般(每次生成都需要写 Zookeeper)。
三、现在企业是如何解决分布式 ID 的问题?
互联网公司(高性能场景):
雪花算法(Snowflake): 常用于订单号、用户 ID 等。
例如:Twitter 原创,国内很多公司(如阿里、字节)都有改进版本。
号段模式: 数据库或缓存预分配号段,适合稳定、高并发场景。
金融领域(有序性要求高):
使用 Zookeeper 顺序节点或基于数据库主键生成。
对事务一致性和顺序要求高的场景。
大规模分布式系统:
利用 Redis 集群作为 ID 生成器,结合雪花算法或分片机制。
5.面试官:单点登录是怎么工作的?
单点登录(SSO) 通过一个统一的认证中心管理 用户登录状态,不同系统之间通过共享 Token 或凭证实现登录信息的同步。它提升了用户体验,同时简化了系统的认证流程。
6.面试官:如何设计安全的对外 API?
如果要设计一个安全的对外 API,我会从以下几个方面入手:
认证和授权:
使用 OAuth 2.0 或 JWT 来认证用户身份,确保调用者合法。
通过角色或权限控制(RBAC/ABAC),限制用户访问特定资源。
数据加密:
强制 HTTPS,确保传输中的数据被加密。
对敏感数据进行字段级加密,并对返回结果做数据脱敏。
防护机制:
使用时间戳和签名机制防止重放攻击。
针对敏感接口,比如登录,加验证码和失败次数限制,防止暴力破解。
实施限流策略,防止恶意刷 API,比如单 IP 每秒限制请求次数。
错误和暴露控制:
返回的错误信息只提供必要信息,避免暴露内部系统细节。
只开放必须的接口,隐藏无关的内部实现。
安全监控:
记录和审计所有 API 请求日志,实时监测异常流量,便于追溯和故障排查。
定期更新:
定期轮换密钥、修补依赖库漏洞,同时进行安全测试,确保系统长期安全。
通过以上方法,可以有效保证对外 API 的数据安全和系统稳定性,同时降低潜在风险。
7.面试官:如果你的项目要支持百万用户,你会如何设计?
和第八题类似,一起回答。
其实本质就是将单体项目逐渐改进到分体项目的过程。首先是把数据和应用分割到两个不同服务器,然后分别优化应用和数据形成各自的集群,引入主副,主从,各种微服务组件。
-
架构设计:分层解耦,支持高并发。我会采用分层架构和分布式设计,分解系统的功能模块,每层专注处理自己的职责。
前端层(负载均衡 + CDN): 部署CDN(内容分发网络),将静态资源如图片、CSS、JavaScript缓存到边缘节点,减少服务器压力,提升用户访问速度。 使用负载均衡器(如 Nginx、HAProxy),将流量分发到多台后端服务器,支持水平扩展。 应用层: 应用服务会采用无状态设计,状态信息存储在缓存或数据库中,方便应用服务扩容。 服务拆分为独立的微服务,按功能解耦(如用户服务、订单服务、支付服务),通过 API 网关(如 Kong)统一管理。 数据层: 使用分布式数据库(如 MySQL 分片、TiDB)支持海量数据存储和查询。 利用读写分离,主库写数据,多个从库读数据,提高读性能。 引入分布式缓存(如 Redis、Memcached)加速高频访问数据,如用户会话、热点数据等。
-
高并发:异步 + 分布式队列
异步处理:对于耗时操作(如下单后发通知),使用消息队列(如 Kafka、RabbitMQ)异步处理,减少用户等待时间。异步任务处理还能平滑流量峰值。限流和降级:在接口层实现限流策略(如漏桶算法、令牌桶算法)来保护系统,防止流量暴增导致崩溃。非核心服务出现压力时,可以降级(如取消某些推荐功能)。
-
数据库设计:分区分库分表
分区和分表:按用户 ID 或订单 ID 对表进行分区或分表,降低单表的数据量,提升查询效率。分库:数据按业务或地理位置拆分到不同的数据库节点,形成分布式数据库集群。事务处理:分布式事务可通过 **两阶段提交(2PC)或最终一致性(TCC 模式) ** 来保证。
-
高可用性:多副本 + 故障恢复
服务高可用:通过服务注册与发现(如 Eureka、Consul),让服务实例自动接管流量,实现无缝扩容或切换。应用层部署多个实例,利用健康检查机制快速剔除故障实例。数据库高可用:数据库采用主从复制或多主架构,主节点故障后快速切换到从节点。灾备设计:跨数据中心部署,关键数据进行定时备份,保证在意外情况下的快速恢复。
-
可扩展性:按需扩容
通过容器化和编排工具(如 Docker + Kubernetes)实现弹性扩容:根据流量动态调整实例数量,低谷时释放资源,高峰时自动扩展。
-
性能优化:监控和调优
全链路监控:部署监控工具(如 Prometheus + Grafana)监测各模块性能,实时报警异常情况。代码和查询优化:数据库查询建立合理索引,避免全表扫描。服务接口按热点和冷门数据优化响应逻辑,提升吞吐量。
8.面试官:如果你的项目用户规模放大了 100 倍,怎么应对?
9.面试官:你的项目如何做到高可用、高吞吐、高扩展性?
高可用的意思就是保证服务尽可能保证处于正常状态,例如4个9,99.99%的时间内都是正常的。这一思路就是主从,集群之类的,保证一台服务器宕机立马会有其他副本服务器顶上。
高吞吐服务需要在一段时间内处理大量请求。常用的指标是 QPS(每秒查询次数)或 TPS(每秒事务次数)。为了实现高吞吐量,我们通常会在架构中添加缓存 ,以避免经过数据库或磁盘等较慢的 I/O 设备。我们还可以为计算密集型任务增加线程数量。 我们还可以在系统中使用异步处理,以有效地单独隔离耗时耗资源的组件。
高扩展性意味着系统可以快速、轻松地扩展,以容纳更多的容量**(横向可扩展性)** 或更多的功能(纵向可扩展性)。 要实现高度可扩展性,需要隔离每个服务的职责。为此,微服务被广泛采用 。我们还利用服务注册和负载平衡器 将请求路由到适当的实例。
10.面试官:CPU 100% 问题怎么排查?
基本思路就是先判断占用cpu资源最多的进程,如果是服务程序大致可以使用两种方式。
系统工具 + jstack: 适合手动分析,步骤清晰,适合初步排查。
Arthas: 提供更友好的交互界面和实时分析功能,适合快速深入定位问题。
top进程,然后找线程,最后找到对应代码块获得占用的核心步骤。