博客记录-day154-面试

一、面试

1、项目问题

1. 怎么防止重复下单?

✅如何解决消息重复消费、重复下单等问题?

防止重复下单可通过多种机制实现:唯一索引约束通过在订单表的用户ID、商品ID等字段建立唯一索引避免重复数据;分布式锁利用Redis或Zookeeper在下单前锁定资源,防止并发冲突;幂等性设计通过生成唯一订单号、Redis的SETNX命令或数据库事务结合唯一索引确保操作仅执行一次;Token令牌机制则要求客户端先获取一次性有效token,服务端校验后处理请求。

2. 采用REDIS分段消费做防超卖的具体机制?

✅库存扣减如何避免超卖和少卖?

Redis分段消费通过将库存拆分为多个子库存(如10个片段),利用DECR/DECRBY命令原子减库存,结合Lua脚本保证操作的原子性。用户下单时随机选择子库存扣减,当某个子库存耗尽时尝试其他片段,从而分散热点数据竞争,提升并发性能。

3. 是否有限流机制?

✅什么是限流?常见的限流算法有哪些?

常见的限流算法包括计数器、滑动窗口、漏桶和令牌桶算法。分布式限流可通过Redis结合Lua脚本实现,结合Sentinel或集群保障高可用;应用层限流则通过Servlet过滤器、Spring AOP或网关(如Gateway)实现,支持灵活应对不同场景的流量控制需求。

2、线程同步与并发编程

1. 还了解其他哪些线程同步方式?

✅线程同步的方式有哪些?

除synchronized外,Java还提供ReentrantLock、ReadWriteLock、StampedLock、Semaphore、CountDownLatch、CyclicBarrier、Phaser、Exchanger等同步工具。原子类(如AtomicInteger)和ThreadLocal通过无锁化或线程本地变量减少竞争,volatile关键字则保证可见性但不确保原子性。

2. SYNCHRONIZE如何保证原子性?

✅synchronized是如何保证原子性、可见性、有序性的?

synchronized通过监视器锁(Monitor)实现互斥,同一时刻仅允许一个线程进入同步块。字节码层面使用monitorenter和monitorexit指令标记同步块,JVM插入内存屏障防止指令重排,确保操作的原子性和可见性。

3. SYNCHRONIZE能否保证有序性?

✅synchronized是如何保证原子性、可见性、有序性的?

synchronized通过内存屏障禁止指令重排,保证同步代码块内的操作有序。其happens-before规则确保同一锁的解锁操作先于后续加锁操作,但对不同锁或非同步代码无效,可能存在跨锁重排。

4. 了解无锁化编程吗?有什么问题?

✅什么是CAS?存在什么问题?

无锁化编程通过CAS、原子类、写时复制等技术实现线程安全,但存在ABA问题(值变化后恢复导致误判)、自旋开销、单变量限制及活锁风险。例如,CAS失败时频繁重试可能浪费CPU资源,复合操作需额外设计保证原子性。

3、线程池

1. 线程池的原理是什么?

✅什么是线程池,如何实现的?

线程池通过核心线程、任务队列、最大线程数和拒绝策略管理任务。提交任务时,优先用核心线程处理;队列满后创建临时线程;资源耗尽则执行拒绝策略(如丢弃任务或抛出异常)。线程复用通过阻塞队列实现,减少线程创建销毁的开销。

2. 如何动态调整线程池参数?

可通过ThreadPoolExecutor的setCorePoolSize()【设置核心线程数】、setMaximumPoolSize()【设置最大线程数】等方法调整参数,或结合配置中心(如Nacos)实时更新。自适应方案监控队列长度和活跃线程数,动态优化参数以适应负载变化。

3. 如何监控线程池状态?

内置方法(如getActiveCount()【返回线程池中​​当前正在执行任务的线程的估计数量​ ​】、getQueue().size()【返回线程池工作队列中​​当前积压的任务数量】)获取实时指标,JMX通过MBean暴露监控数据。自定义监控可定时采集指标并集成Prometheus,分析线程池使用率、任务等待时间及拒绝量,结合Arthas等工具诊断异常。

4. 拒绝策略有哪些适用场景?

✅线程池的拒绝策略有哪些?

AbortPolicy抛出异常,适用于需明确感知任务拒绝的场景;CallerRunsPolicy在调用者线程执行任务,适合降级处理;DiscardPolicy直接丢弃任务,用于非关键数据(如日志);DiscardOldestPolicy移除旧任务优先处理新任务,适用于实时性要求高的场景。

4、JVM内存与垃圾回收

1. 对JVM内存模型(JMM)的了解?

✅什么是Java内存模型(JMM)?

JMM定义多线程内存访问规范,核心为主内存(共享变量)和工作内存(线程私有副本)。通过happens-before规则保证可见性与有序性,如监视器锁规则(解锁先于加锁)、volatile变量规则(写先于读)及传递性等。

2. 垃圾回收算法中标记清除GC Roots可以用哪个?

✅JVM如何判断对象是否存活?

标记阶段从GC Roots遍历可达对象并标记为存活,清除阶段回收未标记对象的内存。优点是实现简单,缺点是产生内存碎片且效率较低,需结合压缩算法(如标记-整理)优化。

3. 如何排查Full GC问题?

✅假设还有很多内存,有什么情况还会频繁fullgc?

通过GC日志分析频率和耗时,使用jmap生成堆转储,借助MAT工具定位内存泄漏或大对象。调整新生代与老年代比例、优化对象生命周期或升级硬件(如增加堆内存)是常见解决方案。

4. Full GC和Young GC的区别?

✅YoungGC和FullGC的触发条件是什么?

Young GC回收新生代(Eden/Survivor区),触发于空间不足,停顿短(毫秒级);Full GC回收整个堆及方法区,触发条件包括老年代不足、System.gc()调用等,停顿长(秒级),影响更大。

5、数据库与索引

1. 数据库索引类型有哪些?

✅什么是聚簇索引和非聚簇索引?

B-Tree索引支持等值和范围查询(如InnoDB主键);哈希索引仅等值查询(Memory引擎);全文索引用于文本搜索(InnoDB 5.6+);空间索引处理地理数据(R-Tree)。按物理结构分为聚集索引(数据与索引同序)和非聚集索引(索引与数据分离)。

2. 如何避免回表?

✅什么是回表,怎么减少回表的次数?

覆盖索引通过查询字段均包含在索引中,直接读取数据无需回表。优化联合索引设计(遵循最左前缀)、使用主键查询(InnoDB聚集索引)或索引下推(提前过滤数据)均可减少回表次数。

3. 主键一般用什么类型?分布式环境下自然ID的缺点?

✅MySQL的主键一定是自增的吗?

整型(自增ID)或UUID是常用主键。自然ID(如自增ID)在分布式系统中存在唯一性冲突、性能瓶颈(集中生成)、迁移困难及安全风险(易被猜测)等问题。

4. 分布式ID生成方式有哪些?

✅Leaf生成分布式ID的原理?

✅什么是雪花算法,怎么保证不重复的?

Snowflake算法生成趋势递增的64位ID(时间戳+机器ID+序列号);数据库号段模式预分配ID范围;Redis自增或Leaf、UidGenerator等系统提供高可用方案。UUID无序但全局唯一,适合非索引场景。

5. B+树为什么适合做索引?

✅什么是B+树,和B树有什么区别?

B+树高度平衡,支持高效范围查询(叶子节点链表连接);非叶子节点仅存键值,容纳更多索引项,降低树高;数据存储在叶子节点,磁盘I/O更少。相比B树,B+树分支因子更大,查询更稳定。

6. B+树如何保持有序?

✅InnoDB为什么使用B+树实现索引?

插入时定位叶子节点并保持有序,节点满则分裂并更新父节点;删除时合并或重分布键值,通过旋转维护平衡。非叶子节点分隔键确保左右子树有序,叶子节点链表支持顺序遍历。

7. B+树相比B树为什么更扁平?

B+树非叶子节点不存数据,可存更多键值,分支因子更高,树高更低。例如,相同节点大小下,B+树存储量是B树的两倍,减少磁盘访问次数,提升查询效率。

6、消息队列

1. 消息队列的使用场景?

✅为什么要使用消息队列?

消息队列用于日志异步处理、数据同步、分布式事务(如事务消息)、流量削峰、延迟任务调度、系统解耦及事件通知等场景,提升系统扩展性和可靠性。

2. 除了RocketMQ还了解哪些消息队列?

✅Kafka、ActiveMQ、RabbitMQ和RocketMQ都有哪些区别?

Kafka高吞吐适合日志和流处理;RabbitMQ基于AMQP,支持复杂路由;Pulsar支持存储计算分离和流批一体;ActiveMQ、NSQ、Redis Streams等各有适用场景,如ZeroMQ轻量级,适合内部通信。

3. Kafka如何保证消息不丢失?

✅Kafka如何保证消息不丢失?

生产者通过acks=all(全副本确认)、重试和幂等性避免丢失;Broker多副本(ISR机制)和持久化存储保障数据冗余;消费者手动提交offset并配合事务确保消费处理原子性。

4. Kafka的Offset有什么作用?

✅Kafka 中的Offset是什么?

Offset标记消费进度,支持手动/自动提交,存储于__consumer_offsets主题。它实现断点续传、消费重放及重平衡时的分区分配,监控Offset可分析消费延迟。

7、网络

1. 浏览器输入域名后的解析过程?

✅浏览器输入www.taobao.com回车之后发生了什么

浏览器解析URL后递归查询DNS:缓存→操作系统→路由器→ISP DNS→根域名服务器→顶级域名服务器→权威服务器,最终获取IP。随后三次握手建立TCP连接,发送HTTP请求,服务器响应后渲染页面,最后关闭连接。

2. 三次握手能否携带数据?

前两次握手(SYN和SYN+ACK)不携带数据,仅建立连接;第三次握手(ACK)确认连接建立,可携带数据,此时客户端进入ESTABLISHED状态,可发送请求。

3. 如何防御SYN攻击?

博客记录-day063-反射机制详解、SPI机制详解+TCP面试题 - 掘金

服务器端启用SYN Cookie、调整TCP参数(增大半连接队列、缩短超时)及限制单IP速率;网络层通过防火墙过滤异常流量;应用层使用CDN或代理隐藏真实服务器,分散攻击压力。客户端防护有限,主要依赖可信网络和代理。

4. 客户端能否做SYN攻击防御?

客户端无法直接防御针对服务器的SYN攻击,但可通过代理访问、检测异常连接或启用备用连接减少风险。企业网络可监控出站流量,防止内部主机发起攻击。

相关推荐
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(75):TiMem——用时间记忆树实现长期记忆的层级巩固
论文阅读·人工智能·学习·开源·github
今夕资源网2 小时前
一只鹈鹕骑着单车闯海岛:开源 3D 网页游戏《鹈鹕骑车》体验与部署教程 github开源
开源·github·ai智能测试题·ai智能测试
沙蒿同学4 小时前
我把架构约定编译成了会变红的测试:Wails v2 + Go + Vue3 桌面脚手架实战
前端·后端·github
落魄大学生之流水线上谋生计5 小时前
幻境相机 Mirage Camera
github
wangruofeng5 小时前
从一个 10 万星 AI Agent 项目里,能学到什么真正的软件工程
github·agent·ai编程
子林super5 小时前
复杂JSON Schema结构与输出校验
github
子林super5 小时前
结构化输出解析失败处理策略
github
怕浪猫6 小时前
拆解 Google《AI Agent Handbook》:企业级 Agent 的六层架构与产品矩阵
面试·github·agent
kali-Myon6 小时前
分享一个网络安全 AI 工具导航项目 SecSkills
安全·ai·github·ctf
峰向AI16 小时前
Kage: 一个 244KB 文件,做出百万级视觉效果
github