1. 项目背景与核心挑战
"黑马点评"是一个典型的互联网高并发场景下的实战项目,它模拟了类似大众点评的商户评价系统。在这个项目中,我们需要处理的核心业务场景包括:用户登录、商户信息展示、点赞收藏、优惠券秒杀等。这些场景都面临着相同的问题——如何在用户量激增时保证系统的稳定性和响应速度。
我最近完整参与了该项目的开发,其中Redis作为核心组件承担了缓存、分布式锁、计数器等关键角色。特别是在促销活动期间,系统需要应对每秒数千次的查询请求和数百次的写操作,传统数据库根本无法承受这样的压力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Redis在项目中的关键应用
2.1 多级缓存架构设计
我们在项目中实现了典型的三级缓存架构:
- 本地缓存(Caffeine):用于存储热点数据,响应时间<1ms
- Redis集群缓存:存储全量商户数据,平均响应时间5ms
- MySQL数据库:数据持久层,配合读写分离
这种架构下,95%的请求都在本地缓存层就被处理了。我们通过Redis的发布订阅功能实现了缓存一致性,关键代码如下:
java复制// 缓存更新监听示例
@EventListener
public void handleCacheUpdate(RedisKeyExpiredEvent event) {
String key = new String(event.getSource());
if(key.startsWith("shop:")) {
localCache.invalidate(key);
}
}
2.2 分布式锁的实现与优化
秒杀场景下我们使用了Redisson实现的分布式锁,相比自己实现的SETNX方案,Redisson提供了更完善的特性:
- 可重入锁设计
- 自动续期机制
- 完善的超时处理
- 看门狗线程保障
典型使用场景:
java复制RLock lock = redissonClient.getLock("coupon:"+couponId);
try {
if(lock.tryLock(1, 10, TimeUnit.SECONDS)) {
// 处理秒杀逻辑
}
} finally {
lock.unlock();
}
3. 高并发场景下的实战技巧
3.1 缓存穿透解决方案
我们遇到了典型的缓存穿透问题:恶意请求查询不存在的商铺ID。最终采用的解决方案组合:
- 布隆过滤器预加载有效ID
- 空值缓存(设置短TTL)
- 接口限流(Guava RateLimiter)
布隆过滤器初始化代码:
java复制// 初始化布隆过滤器
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("shopIds");
bloomFilter.tryInit(100000L, 0.03);
// 加载有效商铺ID
shopDao.findAllIds().forEach(bloomFilter::add);
3.2 热点Key发现与处理
通过Redis的MONITOR命令和自定义注解,我们实现了热点Key的自动发现和动态分散:
java复制@HotKey(expire = 5, timeUnit = TimeUnit.MINUTES)
public Shop getShopById(Long id) {
// 查询逻辑
}
处理策略包括:
- 本地缓存备份
- Key分片(原始Key+随机后缀)
- 请求合并(Hystrix)
4. 性能优化关键指标
经过优化后,系统关键指标对比如下:
| 场景 | 优化前(QPS) | 优化后(QPS) | 提升幅度 |
|---|---|---|---|
| 商铺查询 | 1200 | 8500 | 608% |
| 秒杀下单 | 300 | 2100 | 600% |
| 点赞操作 | 500 | 4000 | 700% |
核心优化手段:
- Pipeline批量操作(提升30%吞吐量)
- Lua脚本保证原子性
- 连接池优化(Lettuce替代Jedis)
5. 踩坑经验与避坑指南
5.1 缓存雪崩防护
我们曾因同时过期导致缓存雪崩,最终解决方案:
- 基础TTL + 随机抖动(1-5分钟)
- 分级缓存(不同级别不同过期时间)
- 熔断降级(Sentinel)
5.2 大数据量扫描优化
避免使用KEYS命令,替代方案:
- SCAN命令分批处理
- 特定前缀+分片设计
- 维护独立的索引集合
java复制// 安全扫描示例
String pattern = "shop:*";
String cursor = "0";
do {
ScanResult<String> scanResult = redisTemplate.scan(
cursor, ScanOptions.scanOptions().match(pattern).count(100).build());
// 处理结果
cursor = scanResult.getCursor();
} while (!"0".equals(cursor));
6. 项目部署与监控
6.1 集群部署方案
我们采用三主三从的Redis集群架构:
- 每个主节点分配不同的哈希槽
- 从节点分布在不同的物理机
- 使用Twemproxy做代理层
关键配置项:
code复制cluster-enabled yes
cluster-node-timeout 15000
cluster-migration-barrier 1
6.2 监控指标采集
通过Prometheus+Grafana构建监控体系,重点监控:
- 内存使用率(<70%)
- 连接数(<maxClients的60%)
- 慢查询(>100ms)
- Key命中率(>95%)
7. 项目扩展与思考
在实际开发中,我们还尝试了以下进阶方案:
- Redis Stream实现消息队列(替代RabbitMQ)
- RedisTimeSeries模块处理时序数据
- RedisGraph处理关联查询
对于想深入学习的开发者,我建议重点掌握:
- Redis底层数据结构实现原理
- RDB/AOF持久化机制
- 集群故障转移流程
- 内存淘汰策略选择
这个项目让我深刻体会到,Redis在高并发系统中绝不是简单的缓存工具,而是整个架构的核心枢纽。合理的设计和优化能让系统性能提升一个数量级,而错误的使用则可能成为系统瓶颈
