共计 2948 个字符,预计需要花费 8 分钟才能阅读完成。
背景分析:现有架构瓶颈
Claude Skills 作为知识分享型网站,随着用户量增长,在高峰时段频繁出现以下问题:

- 数据库 CPU 持续维持在 90% 以上,慢查询日志暴增
- 首页加载时间从 800ms 恶化到 3s+(P95 值)
- 同步发表评论功能在并发提交时出现超时失败
通过 APM 工具定位,主要存在三类瓶颈:
- 单体架构耦合:用户中心、内容服务、推荐引擎共用 MySQL 实例,存在跨模块级联查询
- 缓存穿透:热门文章使用本地 Guava 缓存,节点间数据不一致导致大量请求穿透到 DB
- 同步阻塞:点赞、评论等写操作与核心读链路共享线程池
技术选型对比
架构模式选择
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 开发效率 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| 伸缩性 | ⭐ | ⭐⭐⭐⭐⭐ |
| 故障隔离 | ⭐ | ⭐⭐⭐⭐ |
| 运维成本 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
决策依据:业务已明确划分出内容、用户、推荐等独立领域,且需要独立扩缩容能力,选择 Spring Cloud 微服务架构
缓存方案对比
| 方案 | 吞吐量 | 数据一致性 | 网络开销 |
|---|---|---|---|
| 本地缓存 | 100W ops/s | 差 | 无 |
| Redis 集群 | 10W ops/s | 强 | 有 |
最终设计:采用多级缓存架构,高频不变数据用 Caffeine 本地缓存,分布式场景用 Redis
核心实现
服务拆分策略
- 垂直拆分 按业务领域划分服务:
- content-service:文章 / 评论核心 CRUD
- user-service:账户 / 权限管理
-
recommendation-service:个性化推荐
-
水平拆分 热点数据:
// 按文章 ID 哈希分片 @Service public class ContentSharding { private static final int SHARD_COUNT = 3; public String getDataSourceKey(Long articleId) {return "ds_" + (articleId % SHARD_COUNT); } }
多级缓存设计
// 缓存配置类示例
@Configuration
@EnableCaching
public class CacheConfig {
// 本地缓存(1 分钟过期,最大 1000 条)@Bean
public CacheManager localCache() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}
// Redis 缓存(1 小时过期)@Bean
public RedisCacheConfiguration redisCacheConfig() {return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.disableCachingNullValues();}
}
// 缓存使用示例
@Service
public class ArticleService {@Cacheable(cacheNames = "local_article", key = "#id")
@Cacheable(cacheNames = "redis_article", key = "#id")
public Article getArticle(Long id) {// DB 查询逻辑}
}
消息队列解耦
// 评论异步处理实现
@RestController
public class CommentController {
@Autowired
private KafkaTemplate<String, Comment> kafkaTemplate;
@PostMapping("/comments")
public ResponseEntity<Void> createComment(@RequestBody Comment comment) {kafkaTemplate.send("comment-topic", comment);
return ResponseEntity.accepted().build();
}
}
// 消费者服务
@KafkaListener(topics = "comment-topic")
public void processComment(Comment comment) {// 落库、通知作者等耗时操作}
性能测试数据
| 指标 | 优化前 | 优化后 | 提升幅度 |
|---|---|---|---|
| 首页 QPS | 1200 | 6500 | 441% |
| 评论延迟(P99) | 1200ms | 150ms | 87.5% |
| DB 负载峰值 | 92% CPU | 35% CPU | 62%↓ |
测试环境:8 核 16G × 3 节点,JMeter 模拟 5000 并发用户
生产环境注意事项
缓存雪崩防护
// 缓存过期时间添加随机值
@Bean
public CacheManager redisCacheManager() {return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30).plus(Duration.ofSeconds(new Random().nextInt(300)))))
.build();}
分布式锁实现
// Redisson 分布式锁示例
public void updateArticle(Long id) {RLock lock = redissonClient.getLock("article_lock:" + id);
try {if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {// 业务逻辑}
} finally {lock.unlock();
}
}
监控指标设计
- 基础指标:
- 各服务接口 P99 延迟
- Redis 命中率
-
Kafka 积压消息数
-
自定义埋点:
@Aspect @Component public class CacheMonitor { @Autowired private MeterRegistry registry; @Around("@annotation(cacheable)") public Object monitorCache(ProceedingJoinPoint pjp, Cacheable cacheable) {String cacheName = cacheable.cacheNames()[0]; Timer.Sample sample = Timer.start(registry); try {return pjp.proceed(); } finally {sample.stop(registry.timer("cache.access", "name", cacheName)); } } }
总结与延伸
本方案的核心优化思想可复用于其他内容型网站:
- 服务拆分原则:
- 先按业务领域垂直拆分
-
再对热点数据水平分片
-
缓存设计要点:
- 无状态数据优先本地缓存
-
分布式缓存设置分层过期时间
-
异步化改造:
- 写操作采用消息队列削峰
- 读操作使用缓存兜底
后续可进一步探索:
– 使用 CDN 加速静态资源
– 引入 Elasticsearch 实现复杂搜索
– 尝试服务网格优化服务间通信
正文完
