大家好!我是苏师兄,一名工作多年的程序员,也是公众号【苏师兄编程】的主理人。
一、场景还原:直播带货的「死亡时刻」
面试官:
假设你是某电商系统负责人,某场直播中:
- 粉丝量破亿,实时在线100万人
- 商品秒空,单日订单量达100万单
- 并发请求冲高至200万QPS
突然出现评论区卡死、商品白屏、库存/订单系统崩溃…
你认为问题根源是什么?
二、问题诊断:系统崩溃的三重致命伤
候选人:
这是典型的流量洪峰击穿系统防线引发的多米诺骨牌效应,核心问题集中在三方面:
1️⃣ 流量失控:缺乏分级防护
- 现象:200万QPS直接冲击后端服务
- 危害:服务雪崩,用户体验断崖式下跌
- 数据佐证:库存服务极限QPS仅50万(见候选人回答)
2️⃣ 强耦合依赖:服务间牵连致死
- 典型场景:库存服务宕机→订单系统级联崩溃
- 技术债:服务间未实现「降级熔断」机制
3️⃣ 资源隔离缺失:单点故障扩散
- 致命缺陷:线程池/数据库连接池等资源未隔离
- 后果:普通用户请求耗尽VIP资源池
三、破局之道:系统防护的「三板斧」架构
▶️ 第一斧:流量管控(限流熔断)
// 基于Guava RateLimiter的限流实现(核心代码)
public class RateLimiterService {
private final RateLimiter rateLimiter = RateLimiter.create(500); // 每秒500请求
public boolean tryAcquire(String userId) {
if (rateLimiter.tryAcquire()) {
// 记录用户限流日志
log.info("User {} passed rate limit", userId);
return true;
} else {
throw new RuntimeException("请求过于频繁,请稍后再试");
}
}
}
- 实施要点:
✅ 业务层:用户ID维度限流(防机器人刷单)
✅ 接口层:阶梯式流量控制(如5秒内最多5次请求)
✅ 熔断策略:Resilience4j实现「快速失败+半开机制」
▶️ 第二斧:压力缓冲(削峰填谷)
// Spring Kafka异步处理订单(关键配置)
@Configuration
public class KafkaConfig {
@Bean
public ProducerFactory<String, Order> producerFactory() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(configProps);
}
@Bean
public KafkaTemplate<String, Order> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}
- 技术选型:
✅ 短任务:Redis分布式锁+Lua原子操作
✅ 长任务:RabbitMQ死信队列+重试机制
✅ 排队策略:优先级队列(VIP用户优先处理)
▶️ 第三斧:故障隔离(沙箱防护)
# Spring Cloud Hystrix配置示例(服务隔离)
hystrix:
command:
default:
execution.isolation.thread.timeoutInMilliseconds: 5000
circuitBreaker.requestVolumeThreshold: 20
circuitBreaker.sleepWindowInMilliseconds: 5000
circuitBreaker.errorThresholdPercentage: 50
- 隔离策略:
🌐 线程隔离:为VIP服务单独分配线程池
🛡️ 服务降级:支付失败时走「短信通知」备用路径
🔐 数据隔离:核心交易库使用独立实例
四、面试官追问:熔断机制的局限性
面试官:
如果库存服务熔断后,用户疯狂重试导致订单服务崩溃,除了熔断还有更好方案吗?
候选人:
这需要组合策略:
- 前端限流:页面按钮点击间隔≥3秒(JavaScript防抖)
- 流量染色:标记重试请求,限制同一用户请求频率
- 异步解耦:前端返回「排队中」,后台通过WebSocket推送结果
- 熔断增强:结合「请求合并」策略,批量处理相同订单请求
五、高阶技巧:隐藏瓶颈的排查指南
面试官:
当系统卡顿但资源使用率正常时,如何快速定位瓶颈?
候选人:
我会采用三步定位法:
- 调用链分析:通过SkyWalking抓取慢请求TOP10
- 线程Dump:分析
jstack
输出查找阻塞点- 协议分析:Wireshark抓包检查TCP握手耗时
六、Java并发编程的深度优化
1️⃣ 线程池调优实践
// 自定义线程池配置(核心参数解析)
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100); // 核心线程数
executor.setMaxPoolSize(500); // 最大线程数
executor.setQueueCapacity(1000); // 队列容量
executor.setKeepAliveSeconds(60); // 线程空闲存活时间
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
- 调优原则:
✅ 核心线程数=CPU核心数×(1+平均等待时间/平均服务时间)
✅ 队列容量=QPS×平均响应时间×冗余因子
2️⃣ 分布式锁的实现方案
// Redisson分布式锁(可重入锁示例)
RLock lock = redissonClient.getLock("order_lock:" + orderId);
try {
if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
// 执行库存扣减
}
} finally {
lock.unlock();
}
- 对比方案:
✓ 基于数据库的乐观锁(适合低并发场景)
✓ 基于ZooKeeper的临时顺序节点锁(强一致性)
七、数据库分库分表实战
1️⃣ 分库分表规则设计
-- 按用户ID哈希分库分表(示例规则)
CREATE TABLE IF NOT EXISTS t_order_0001 (
order_id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
amount DECIMAL(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 分片函数(Java实现)
public class HashShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
Long userId = shardingValue.getValue();
int hash = userId.hashCode() & Integer.MAX_VALUE;
return "t_order_" + (hash % 16); // 16个分片
}
}
2️⃣ 读写分离配置
# MyBatis Plus读写分离配置
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSourceRouter routingDataSource() {
DataSourceRouter router = new DataSourceRouter();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", masterDataSource());
targetDataSources.put("slave", slaveDataSource());
router.setTargetDataSources(targetDataSources);
router.setDefaultTargetDataSource(masterDataSource());
return router;
}
}
八、性能测试与容量评估
1️⃣ 全链路压测方案
# JMeter压测脚本片段
ThreadGroup:
Number of Threads (Users): 10000
Ramp-Up Period (in seconds): 60
Loop Count: 100
HTTP Request:
Server Name or IP: localhost
Path: /api/createOrder
Method: POST
Parameters: productId=12345&amount=100.00
2️⃣ 容量评估模型
系统容量 = (单实例QPS × 实例数) / (1 + 并发系数)
并发系数 = (数据库连接数 + 线程数 + 网络连接数) / 单实例资源上限
- 案例数据:
某电商系统通过该模型评估,从8核16G单实例扩容至16核32G×3节点,支撑QPS从5万提升至18万
九、监控与运维体系
1️⃣ 核心监控指标
指标类型 | 监控项 | 告警阈值 |
---|---|---|
基础资源 | CPU使用率 | >80% |
内存使用率 | >90% | |
磁盘I/O延迟 | >500ms | |
网络 | 网卡吞吐量 | >90%带宽 |
应用层 | 接口响应时间 | >2s(核心业务) |
错误率 | >0.1% | |
分布式系统 | 消息队列积压量 | >10万条 |
分片热点度 | >80% |
2️⃣ 自动化运维
# 腾讯云弹性伸缩配置示例
{
"scaling_policy": {
"adjustment_type": "CHANGE_IN_CAPACITY",
"cool_down": 300,
"scaling_adjustment": 2
},
"metric_trigger": {
"metric_name": "CPUUtilization",
"statistic": "Average",
"comparison_operator": "GREATER_THAN",
"threshold": 70,
"period": 60
}
}
十、总结:系统设计的哲学思考
金句摘录:
▶️ 「稳定性不是功能,而是架构设计的基本素养」
▶️ 「最好的防御是主动攻击——常态化压测」
▶️ 「永远为最坏情况预留20%的系统冗余」
关注我,获取更多技术干货~
顶级程序员都在偷偷看的书单!免费领50+本技术神作
关注公众号【苏师兄编程】,回复“书单”,即可领取上面书单