引言:一个点赞背后的技术挑战
在当今的直播和短视频时代,我们经常会看到这样的场景:直播间人数突破10万+,点赞数从千万飙升至亿级。用户轻点屏幕的简单动作------「❤️+1」,背后却需要应对巨大的技术挑战。当百万用户同时为同一个直播间点赞时,如何保证系统稳定运行?这就是我们今天要深入探讨的高并发架构设计。
技术演进之路
第一阶段:朴素方案与性能瓶颈
大多数开发者在初次实现点赞功能时,都会采用最直接的方案:
sql
-- 最基础的点赞实现
UPDATE post
SET like_count = like_count + 1
WHERE id = #{postId};
方案分析:
-
✅ 逻辑简单,易于实现
-
✅ 数据强一致性保证
-
❌ 高并发下性能瓶颈明显
-
❌ 行锁竞争导致响应延迟
适用场景: 小型博客、论坛等低并发场景
第二阶段:Redis缓存架构
面对高并发挑战,我们引入Redis作为缓存层:
typescript
@Service
public class LikeService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void addLike(Long roomId) {
String key = "like:room:" + roomId;
// Redis原子自增,支撑10万+ QPS
redisTemplate.opsForValue().increment(key, 1);
}
}
架构优势:
-
内存操作,性能提升100倍以上
-
原子操作保证并发安全
-
轻松支撑10万级QPS
第三阶段:数据持久化与最终一致性
为了解决Redis数据持久化问题,我们引入定时同步机制:
ini
@Scheduled(cron = "0 */5 * * * ?")
public void syncLikeCountToDB() {
Set<String> keys = redisTemplate.keys("like:room:*");
for (String key : keys) {
Long roomId = extractRoomId(key);
Long redisCount = getLikeCount(roomId);
// 批量更新数据库,减少IO压力
postMapper.batchUpdateLikeCount(roomId, redisCount);
}
}
前端优化策略
请求合并与防抖机制
javascript
class LikeManager {
constructor() {
this.pendingLikes = new Map();
this.batchSize = 10;
this.debounceTime = 3000;
}
async addLike(roomId, userId) {
const key = `${roomId}-${userId}`;
const currentCount = this.pendingLikes.get(key) || 0;
this.pendingLikes.set(key, currentCount + 1);
// 批量提交条件:达到阈值或超时
if (this.shouldSubmitBatch()) {
await this.submitBatchLikes();
}
}
async submitBatchLikes() {
const batchData = Array.from(this.pendingLikes.entries())
.map(([key, count]) => {
const [roomId, userId] = key.split('-');
return { roomId, userId, count };
});
await fetch('/api/like/batch', {
method: 'POST',
body: JSON.stringify(batchData)
});
this.pendingLikes.clear();
}
}
分布式架构设计
数据分片策略
当单机Redis无法满足需求时,我们采用Redis Cluster进行水平扩展:
ini
@Component
public class DistributedLikeService {
public String getShardKey(Long roomId) {
// 基于房间ID进行分片
int shardCount = 16; // 16个分片
int shardIndex = roomId.hashCode() % shardCount;
return "like:shard:" + shardIndex + ":room:" + roomId;
}
public void addLike(Long roomId, Long userId) {
String countKey = getShardKey(roomId);
String userKey = countKey + ":users";
// 使用Lua脚本保证原子性
String luaScript = """
if redis.call('SADD', KEYS[2], ARGV[1]) == 1 then
return redis.call('INCRBY', KEYS[1], 1)
else
return -1
end
""";
redisTemplate.execute(luaScript,
Arrays.asList(countKey, userKey),
userId.toString());
}
}
防止重复点赞
vbnet
public boolean addLikeWithDeduplication(Long roomId, Long userId) {
String lockKey = "like:lock:" + roomId + ":" + userId;
// 分布式锁防止重复提交
Boolean lockAcquired = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", Duration.ofSeconds(5));
if (Boolean.TRUE.equals(lockAcquired)) {
try {
return doAddLike(roomId, userId);
} finally {
redisTemplate.delete(lockKey);
}
}
return false;
}
完整系统架构
数据流向设计
用户端 → 负载均衡 → 应用集群 → Redis Cluster → 定时任务 → MySQL分库
各层职责:
-
客户端:请求合并、本地缓存
-
网关层:限流、鉴权、负载均衡
-
应用层:业务逻辑、幂等控制
-
缓存层:高并发计数、分布式锁
-
存储层:数据持久化、批量操作
性能对比分析

监控与容灾
关键指标监控
java
@Component
public class LikeMonitor {
@Autowired
private MeterRegistry meterRegistry;
private final Counter likeCounter = Counter
.builder("like.requests")
.description("点赞请求计数")
.register(meterRegistry);
private final Timer likeTimer = Timer
.builder("like.duration")
.description("点赞处理时长")
.register(meterRegistry);
public void recordLikeRequest(boolean success, long duration) {
likeCounter.increment();
likeTimer.record(duration, TimeUnit.MILLISECONDS);
if (!success) {
meterRegistry.counter("like.errors").increment();
}
}
}
降级策略
kotlin
@Service
public class LikeServiceWithFallback {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@HystrixCommand(fallbackMethod = "localCacheFallback")
public boolean addLikeWithFallback(Long roomId, Long userId) {
return addLike(roomId, userId);
}
public boolean localCacheFallback(Long roomId, Long userId) {
// 本地缓存降级方案
log.warn("使用本地缓存降级方案");
return true; // 保证用户体验
}
}
总结与最佳实践
核心设计原则
-
读写分离:读操作走缓存,写操作异步化
-
批量处理:合并请求减少IO压力
-
最终一致:在性能和一致性间取得平衡
-
水平扩展:通过分片支持系统扩容
技术选型建议
-
初创阶段:Redis单机 + MySQL
-
成长阶段:Redis主从 + 批量同步
-
成熟阶段:Redis Cluster + 分库分表
-
大型平台:多机房部署 + 异地容灾
经验总结
点赞系统的演进历程,正是互联网架构发展的缩影。从简单的单机方案到复杂的分布式系统,每一步演进都是为了在性能、成本和可维护性之间找到最佳平衡点。
关键洞察:
-
没有完美的架构,只有适合业务的架构
-
过度设计比设计不足更危险
-
监控和可观测性比功能开发更重要
-
用户体验是技术决策的最终导向
当下次你在直播间疯狂点赞时,不妨想想背后这套精密运转的技术体系。正是这些看不见的技术细节,支撑着我们顺畅的数字生活体验。