视频通过拆解问题根源与对应方案,给出了保证 Kafka 消息顺序消费的完整逻辑。
问题根源:视频指出导致消息乱序的三个核心场景,包括消息分散到不同分区、消费端多线程处理、异常处理机制(如消费失败重试、自动提交偏移量)。
解决方案:针对问题提出三个对应措施,包括将有序要求的消息通过指定分区或相同 key 路由到同一分区、消费端采用单线程或按业务 key 分配线程、手动提交偏移量并处理失败消息。
权衡原则:视频强调强顺序性与高性能存在冲突,实际应用需结合业务场景权衡,允许最终一致性时可放宽要求以提高吞吐量。
视频最后明确,业务必须严格顺序时采用上述方案,允许短暂乱序时可优先保证吞吐量。
高并发 API 访问量统计的核心考察点并非代码实现,而是异步解耦与分层架构思维。
Kafka+Redis 方案:通过 AOP 或过滤器拦截请求,将日志异步写入 Kafka 队列,消费服务利用滑动窗口算法计算 10 分钟访问量,结果以有序集合形式存入 Redis,前端看板通过 ZREVRANGE 命令获取 TopN 数据。
ELK 方案:复用现有 ELK 体系,由 Logstash 采集解析日志并写入 ES,通过 ES 聚合查询按时间过滤并分组计数,Kibana 配置 Dashboard 实现看板展示。
选型逻辑:追求极致实时性选 Kafka+Redis,依赖现有基建选 ELK 降本增效。
视频明确指出,高并发场景下同步处理会导致数据不准且拖垮主线程,异步解耦是核心解决方案。
仅知道给单例对象加 volatile 无法通过资深 Java 工程师的面试。
问题场景:线上共享数据缓存使用双重检查锁定单例模式,偶发获取到属性不完整的对象。
面试者回答:提出给对象加 volatile 关键字,但无法解释其原理。
核心考点:volatile 仅保证可见性和有序性,无法保证原子性;双重检查锁定中 new 操作的指令重排可能导致线程拿到未初始化完成的对象。
并发素养四层:理解 JMM 内存模型及 happens-before 原则、掌握正确的单例实现方式(如静态内部类、枚举单例)、使用 jstack 和 Arthas 等工具排查并发问题、设计阶段考虑线程安全方案(如并发容器选择、锁顺序统一)。
视频强调并发 bug 的定位需依赖对 JMM 的透彻理解,而非仅依赖表面解决方案。
线程池任务超出核心配置时的处理逻辑需结合队列与最大线程数参数共同判断。
执行流程:任务提交后先检查核心线程数,未达上限则创建核心线程;核心线程满后尝试入队;队列满且未达最大线程数时创建非核心线程;均满时触发拒绝策略。
参数推演:以核心线程 5、最大线程 10、队列长度 0 为例,前 5 个任务直接创建核心线程;第 6 至 10 个任务因队列满创建非核心线程;第 11 至 15 个任务触发拒绝策略。
实际建议:工作中阻塞队列一般不为 0,即使使用无存储的 SynchronousQueue 也可用于数据交互。
视频通过具体参数案例讲解线程池核心原理,可帮助面试者清晰展示对线程池机制的理解。
Java注解原理仅回答 "反射" 会暴露对注解原理的理解不完整,难以通过大厂面试。
生命周期:注解分为 source、class、runtime 三个级别。source 级别在编译后被丢弃,class 级别记录在 class 文件但 JVM 加载时忽略,runtime 级别会永久保留且可通过反射读取。
处理机制:Spring 的 @Autowired 依赖注入并非主要依赖反射,而是在容器启动时通过字节码增强或后置处理器提前扫描处理。
定义方式:用 @interface 关键字定义注解,需使用元注解和 @Retention 指定注解的作用范围。
回答模板:面试时需从本质论(注解是元数据标签)、生命周期论(三个级别及反射限制)、实现机制(编译器或框架处理注解)三个层面完整回答。
视频提供了自定义注解实现日志脱敏、AOP 中获取私有方法注解参数等实战场景的延伸方向。