欢迎点击下方👇关注我,记得星标哟~
文末会有重磅福利赠送
最近由于三大外卖平台“打仗”,优惠券多到数不过来,一日三餐每个平台各点一单哈哈哈,正好最近组织内部还有朋友在北京的京东面试过,分享一下她的面经(Java岗):
Kafka 本身通过副本机制、生产者确认(acks)、消费者手动提交等设计理论上可以实现消息不丢失,但在实际分布式系统中,由于业务逻辑复杂性、中间件与业务操作的原子性难以保障,仍需要引入“本地消息表”等额外机制。以下是具体原因及解决方案的对比分析:
Kafka 消息不丢失的机制及其局限性
acks=-1:要求所有 ISR(同步副本)确认写入成功,否则重试。retries 和 retry.backoff.ms 应对网络抖动。replication.factor≥3 + min.insync.replicas≥2,避免单点故障丢失数据。enable.auto.commit,业务处理成功后再提交 offset,避免消息未处理就被标记消费。Kafka 机制的局限性
unclean.leader.election 配置可能导致数据丢失。为什么需要本地消息表?解决哪些 Kafka 无法覆盖的问题 本地消息表的核心是将业务操作与消息发送/消费绑定为原子操作,通过业务数据库事务保证一致性:
1. 生产者端:解决“发送后丢失”问题
2. 消费者端:解决“消费后丢失”问题
3. 关键价值:弥补分布式事务缺口
生产建议:
idempotent producer(幂等生产者)减少重复发送,而非完全依赖本地表。总结:Kafka 与本地消息表的关系 Kafka 的可靠性机制解决消息在管道内的传输问题,而本地消息表解决业务操作与消息状态的全局一致性问题。二者是互补而非替代关系:
在分布式系统中,通过守护线程监控任务状态并同步到数据库时,若任务执行完成但状态更新前发生宕机,需通过以下机制保证一致性。具体解决方案如下:
1. 核心问题:宕机导致状态丢失的风险
2. 解决方案:原子性保障 + 故障恢复机制
updateStatus 失败,事务回滚,任务结果不会被确认。UPDATE status SET state='done' WHERE id=task_id AND state!='done')。3. 总结:关键设计原则
生产建议:
idempotent producer)避免消息重复。Dubbo 是一个高性能 Java RPC 框架,其核心执行流程如下:
@Reference 注解注入服务)。MySQL 索引失效的常见场景包括:
(a,b,c) 下,查询条件缺失 a 或未按顺序使用索引列(如 WHERE b=1)。WHERE YEAR(create_time)=2023 或 WHERE amount*2>100。WHERE code=100,实际 code 为 VARCHAR)。OR 连接非索引列:WHERE a=1 OR b=2,若 b 无索引则全表扫描。LIKE 以通配符开头:WHERE name LIKE '%abc' 无法利用索引(LIKE 'abc%' 有效)。MVCC(多版本并发控制)是 InnoDB 实现高并发的核心机制:
DB_TRX_ID(最近事务 ID)和 DB_ROLL_PTR(回滚指针)。DB_TRX_ID 小于 Read View 中最小事务 ID → 可见(已提交)。DB_TRX_ID 大于 Read View 中最大事务 ID → 不可见(未提交)。DB_TRX_ID 在活跃事务列表中 → 不可见(未提交);否则可见。key:null),并设置短过期时间。key:null),并设置短过期时间。30min + rand(10min))。30min + rand(10min))。Redis 高性能的核心设计:
Redis 6.0+ 优化:网络 I/O 多线程化提升吞吐量,但命令执行仍保持单线程以保证原子性。
维度 | Spring | Spring Boot |
|---|---|---|
配置方式 | 需手动配置 XML/注解,依赖管理复杂。 | 自动配置(@EnableAutoConfiguration),简化依赖(Starter 包)。 |
内嵌服务器 | 需外部部署(如 Tomcat)。 | 内置 Tomcat/Jetty,无需单独部署。 |
监控与运维 | 需集成 Spring Actuator 等模块。 | 内置 Actuator,提供健康检查、指标收集等。 |
开发效率 | 需大量样板代码。 | 约定优于配置,快速构建独立应用。 |
自动装配通过以下流程实现:
@SpringBootApplication:@EnableAutoConfiguration,触发自动配置加载。spring.factories:META-INF/spring.factories 文件,读取 AutoConfiguration 类列表。@ConditionalOnClass、@ConditionalOnProperty 等注解,按需实例化 Bean(如仅当存在 DataSource.class 时配置数据库连接)。@Bean 方法将对象注册到 IoC 容器。@Autowired 是如何把 Bean 注入进去的@Autowired 注入流程分为四个阶段:
AutowiredAnnotationBeanPostProcessor 扫描被 @Component 标记的类,识别带 @Autowired 的字段/方法。InjectionMetadata 对象。UserService)。userService)。@Qualifier 指定:强制按名称注入(如 @Qualifier("masterDB"))。List<Interface> 注入所有实现类;Map<String, Interface> 的 Key 为 Bean 名称。@PostConstruct 中转)。底层原理:依赖解析由
DefaultListableBeanFactory.doResolveDependency()完成,最终通过Field.set()或方法反射注入。
一、核心差异
维度 | Elasticsearch | MySQL |
|---|---|---|
数据模型 | 文档型(JSON),倒排索引支持全文搜索。 | 关系型(行列),B+树索引支持事务。 |
分布式架构 | 原生分片,横向扩展至数千节点。 | 单机为主,分库分表需中间件。 |
查询场景 | 多字段组合查询高效(如 title:手机 AND price:[1000 TO 2000])。 | 事务操作(ACID)、关联查询(JOIN)高效。 |
二、节点与副本配置
number_of_replicas: 0),但宕机时数据可能丢失。模板方法模式:
核心思想:
实现示例:
public abstractclass DataProcessor {
// 模板方法(final 防止篡改)
public final void process() {
connect(); // 固定步骤
transform(); // 抽象方法(子类实现)
disconnect(); // 固定步骤
}
private void connect() { /* 数据库连接逻辑 */ }
protected abstract void transform(); // 由子类自定义
private void disconnect() { /* 断开连接 */ }
}
publicclass CSVProcessor extends DataProcessor {
@Override
protected void transform() {
System.out.println("解析 CSV 数据...");
}
}
应用场景:
JdbcTemplate,用户实现 RowMapper 处理结果集。优势: