1. 百万级点赞系统的核心挑战
每天处理千万级请求的点赞系统,本质上是在解决"原子计数器"的分布式一致性问题。去年我们重构某社交平台点赞模块时,峰值QPS达到12万,单个热点内容30分钟内收到超过50万次点赞请求。这种场景下,传统基于关系型数据库的方案会出现两个致命问题:一方面InnoDB的行锁竞争导致吞吐量急剧下降;另一方面频繁的磁盘IO使得响应时间突破1秒,直接影响用户体验。
真正的高并发系统设计必须同时满足三个核心指标:
- 99.9%的请求响应时间<50ms
- 数据持久化延迟<5秒
- 计数器误差率<0.001%
2. 架构设计的三层解耦方案
2.1 接入层:请求预处理与负载均衡
我们采用Nginx + Lua实现的第一层过滤能拦截90%的无效请求。关键配置包括:
nginx复制location /like {
access_by_lua_file /path/to/rate_limiter.lua;
proxy_pass http://backend;
}
其中rate_limiter.lua实现了基于令牌桶的限流算法,单个IP限制为10次/秒。实测表明,这种方案比纯Nginx的limit_req模块节省30%的CPU开销。
重要提示:必须设置burst参数应对突发流量,我们配置burst=1000可平稳度过明星发布时的流量尖峰
2.2 逻辑层:异步化处理管道
核心架构采用Disruptor环形队列实现生产者-消费者模型。事件处理流程如下:
- 请求经校验后生成LikeEvent
- 入队时采用多线程CAS操作
- 消费者批量聚合(每100ms或满1000条触发)
- 通过双Buffer机制切换读写指针
这种设计在8核服务器上可实现单机50万TPS,内存占用稳定在2GB以内。关键参数配置:
java复制// Disruptor初始化配置
disruptor.setBufferSize(1 << 21); // 2^21个槽位
disruptor.setThreadFactory(new CustomThreadFactory());
2.3 存储层:分级持久化策略
我们创新性地设计了三级存储体系:
- 内存计数器:ConcurrentHashMap分片存储,每分片对应一个自旋锁
- 分布式缓存:Redis集群采用CRC16分片,配合pipeline批量写入
- 最终存储:MySQL使用INSERT DELAYED + 定时合并策略
数据一致性通过两阶段提交保证:
python复制def commit_transaction():
try:
redis.multi()
redis.incr(counter_key)
redis.zadd(rank_key, timestamp)
redis.execute()
mysql.queue_async_commit()
except:
mysql.rollback()
raise
3. 性能优化实战技巧
3.1 热点数据动态分片
当检测到单个key的QPS超过5000时,自动触发分片策略:
- 基础key转为hash结构
- 客户端随机选择分片写入
- 汇总时使用SCAN+HGETALL
实测某明星结婚官宣的帖子,分片后写入性能提升8倍,从原来的12000 QPS提升到96000 QPS。
3.2 零拷贝日志收集
采用mmap实现的文件日志比传统FileChannel快40%:
java复制RandomAccessFile raf = new RandomAccessFile(file, "rw");
MappedByteBuffer buffer = raf.getChannel().map(
FileChannel.MapMode.READ_WRITE, 0, 1 << 30);
3.3 智能降级策略
基于历史数据动态调整服务等级:
- 正常状态:全量数据同步
- 压力阈值1:关闭排行榜计算
- 压力阈值2:降级为内存计数
- 极端情况:返回静态缓存值
4. 监控体系的特殊设计
4.1 多维度量指标
我们采集的23项核心指标包括:
| 指标名称 | 采集频率 | 报警阈值 |
|---|---|---|
| 写入延迟P99 | 10s | >80ms |
| 内存分片倾斜率 | 1m | >30% |
| 批量提交失败率 | 30s | >0.1% |
4.2 追踪链路染色
通过注入TraceID实现全链路追踪:
go复制func HandleLike(ctx context.Context) {
span, ctx := opentracing.StartSpanFromContext(ctx, "like")
defer span.Finish()
// ...业务逻辑
}
5. 容灾演练的宝贵经验
我们每月进行的混沌工程测试发现:
- Redis主从切换时会出现0.1%的数据偏差
- 网络分区时内存计数可能溢出
- 批量提交间隔不宜超过3秒
解决方案包括:
- 增加CRC32校验环节
- 设置计数器上限告警
- 实现断点续传机制
在最近一次机房断电演练中,系统在30秒内自动切换到灾备中心,数据零丢失。这得益于我们设计的双活架构,关键配置如下:
yaml复制# 数据中心配置
datacenters:
- id: dc1
redis: redis://cluster1
mysql: jdbc:mysql://master1
- id: dc2
redis: redis://cluster2
mysql: jdbc:mysql://master2
这套系统经过618大促的实战检验,当日处理点赞请求2.3亿次,峰值QPS达到15万,期间CPU利用率保持在70%以下。最关键的收获是:高并发系统不是简单的组件堆砌,而是需要针对业务特点进行深度定制化设计。比如我们发现点赞请求具有明显的时间局部性特征,因此采用的特殊缓存预热策略,使得缓存命中率始终保持在99.8%以上。