黑马点评遇到的问题
时间: 2025-03-09 11:15:11 浏览: 60
<think>好的,我现在要处理用户关于黑马点评项目遇到的问题及解决方案的查询。首先,我需要理解用户的具体需求。黑马点评是一个实战项目,通常涉及Redis、分布式锁、缓存穿透、缓存击穿、缓存雪崩等问题。用户可能在学习或开发过程中遇到了这些常见问题,需要解决方案。
接下来,我需要确定用户的问题范围。根据常见的黑马点评项目案例,可能的问题点包括缓存一致性、分布式锁的实现、秒杀库存超卖、商户查询缓存穿透、数据一致性和并发竞争等。因此,我需要针对这些方面进行搜索和整理。
现在,我需要调用网络搜索工具,查找相关的解决方案。例如,缓存穿透可以通过布隆过滤器或缓存空对象解决;分布式锁可以使用Redis的SETNX命令或Redisson框架;缓存雪崩可以通过随机过期时间或永不过期策略来应对。秒杀库存超卖问题通常用乐观锁或Redis原子操作处理。商户查询缓存可能需要双重检查锁和延迟双删策略来保证一致性。
在整合信息时,要确保每个解决方案清晰且步骤分明,避免使用第一人称和步骤词汇。同时,注意引用内容要分散在回答中,而不是集中在末尾。例如,在解释缓存穿透时,直接提到布隆过滤器和缓存空对象,并给出代码示例。
然后,检查格式是否符合要求:数学公式和代码是否正确标注,相关问题部分是否包含三个基于回答的问题,比如缓存穿透与雪崩的区别、Redisson分布式锁实现原理、乐观锁在超卖中的应用等。
最后,确保整个回答结构符合用户的要求,每个方法或步骤之间换行,没有使用Markdown格式,相关问题部分正确使用标题和编号。完成后,再复查一遍是否遗漏了任何用户指定的格式要求,比如代码块的语言类型、公式的$符号等。</think>针对黑马点评项目中的典型技术问题,结合高频解决方案整理如下:
**缓存穿透解决方案**
- 采用布隆过滤器预校验请求合法性,拦截非法ID查询
- 对无效请求结果进行空值缓存并设置短过期时间(如2-3分钟)
```java
public Shop queryWithPassThrough(Long id) {
String key = CACHE_SHOP_KEY + id;
// 1.尝试从缓存获取
String shopJson = stringRedisTemplate.opsForValue().get(key);
if (StrUtil.isNotBlank(shopJson)) {
return JSONUtil.toBean(shopJson, Shop.class);
}
// 2.判断是否命中空值
if (shopJson != null) {
return null;
}
// 3.未命中则查询数据库
Shop shop = getById(id);
if (shop == null) {
// 将空值写入Redis
stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);
return null;
}
// 4.数据库存在则写入Redis
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);
return shop;
}
```
**分布式锁实现方案**
- 基于Redis的SETNX命令实现互斥锁
- 使用Redisson框架实现可重入锁,避免死锁问题
```java
public void deductStock() {
RLock lock = redissonClient.getLock("lock:stock");
try {
lock.lock();
// 业务逻辑
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
if (stock > 0) {
int realStock = stock - 1;
stringRedisTemplate.opsForValue().set("stock", realStock + "");
}
} finally {
lock.unlock();
}
}
```
**缓存雪崩预防策略**
- 设置差异化的缓存过期时间,公式:$TTL = baseTime + randomDelta$
- 建立多级缓存架构(Redis+本地缓存)
- 热点数据采用永不过期策略,配合异步更新
**秒杀库存超卖处理**
- 基于Redis的原子操作实现库存扣减
```lua
local stock = KEYS[1]
local num = ARGV[1]
if (tonumber(redis.call('get', stock)) >= tonumber(num)) then
return redis.call('incrby', stock, -num)
end
return -1
```
- 数据库层使用乐观锁控制版本号
```sql
UPDATE stock SET count = count -1, version = version +1
WHERE id = #{id} AND version = #{version}
```
**商户查询缓存一致性方案**
- 采用延迟双删策略保证最终一致性
```java
public void updateShop(Shop shop) {
// 1.先更新数据库
updateById(shop);
// 2.删除缓存
redisTemplate.delete(CACHE_SHOP_KEY + shop.getId());
// 3.延迟再次删除
executorService.schedule(() -> {
redisTemplate.delete(CACHE_SHOP_KEY + shop.getId());
}, 1, TimeUnit.SECONDS);
}
```
**缓存击穿应对方法**
- 使用互斥锁实现热点数据重建的串行化
- 逻辑过期方案设计(物理不过期,业务层控制有效期)
阅读全文
相关推荐


















