Java+RedisTemplate:解锁高阶玩法,从缓存到分布式锁
·
01
场景一
商品详情缓存 —— 秒杀不卡,就靠它!
痛点:商品详情页 QPS 高到离谱,数据库顶不住。
方案:Redis 做缓存,过期时间兜底,防雪崩。
@Service
public class ProductCacheService {
private static final String PRODUCT_KEY_PREFIX = "product:";
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 先查缓存,再查 DB,最后回写缓存
*/
public String getProductInfo(String productId) {
String key = PRODUCT_KEY_PREFIX + productId;
// 1️⃣ 读缓存
String productInfo = redisTemplate.opsForValue().get(key);
if (productInfo == null) {
// 2️⃣ 缓存未命中 → 查库
productInfo = getProductInfoFromDB(productId);
if (productInfo != null) {
// 3️⃣ 写缓存 + 过期时间 60s,防雪崩
redisTemplate.opsForValue().set(key, productInfo, 60, TimeUnit.SECONDS);
}
}
return productInfo;
}
private String getProductInfoFromDB(String productId) {
// 伪代码:实际走 MyBatis / JPA
return "商品名称: 机械键盘,价格: 299 元";
}
}
注解
-
1. 前缀设计
product:,可读性高,方便批量删除。 -
2. 过期时间 60 秒,既防雪崩又保热数据。
-
3. 空值穿透保护 可再加布隆过滤器,这里留给你扩展。
02
场景二
点赞计数器 —— 高并发也稳如老狗
痛点:社交 App 点赞数实时更新,MySQL 顶不住。
方案:Redis 原子自增,一行代码解决并发。
@Service
public class LikeCounterService {
private static final String LIKE_KEY_PREFIX = "dynamic:like:";
@Autowired
private RedisTemplate<String, Long> redisTemplate;
/**
* 点赞 +1
*/
public long like(String dynamicId) {
String key = LIKE_KEY_PREFIX + dynamicId;
return redisTemplate.opsForValue().increment(key);
}
/**
* 取消点赞 -1
*/
public long unlike(String dynamicId) {
String key = LIKE_KEY_PREFIX + dynamicId;
return redisTemplate.opsForValue().increment(key, -1);
}
/**
* 查询当前点赞数
*/
public long getLikes(String dynamicId) {
String key = LIKE_KEY_PREFIX + dynamicId;
Long likes = redisTemplate.opsForValue().get(key);
return likes == null ? 0L : likes;
}
}
注解
-
1. 原子自增
increment保证并发安全,一行代码顶 100 行 Java 锁。 -
2. 前缀动态拼接 方便统计某条动态。
-
3. 返回值直接用 前端实时刷新,无延迟。
03
场景三
消息队列 —— 服务解耦神器
痛点:订单服务要通知库存服务,但不想直接调接口。
方案:Redis List 做轻量 MQ,左进右出,无依赖。
@Component
public class RedisQueue {
private static final String TASK_QUEUE = "task_queue";
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 生产者:左进队列
*/
public void send(String message) {
redisTemplate.opsForList().leftPush(TASK_QUEUE, message);
}
/**
* 消费者:右出队列,非阻塞
*/
public String receive() {
return redisTemplate.opsForList().rightPop(TASK_QUEUE);
}
/**
* 带超时的阻塞消费(可重试)
*/
public String receiveBlocking(long timeout, TimeUnit unit) {
return redisTemplate.opsForList().rightPop(TASK_QUEUE, timeout, unit);
}
}
注解
-
1. 左进右出 保序,天然 FIFO。
-
2. 非阻塞 / 阻塞双模式 适配不同业务节奏。
-
3. 无外部依赖 不想上 Kafka?Redis List 顶一波先。
04
场景四
分布式锁 —— 高并发抢资源的“红绿灯”
痛点:多实例同时写文件,怕写串。
方案:Redis 分布式锁,setIfAbsent + 过期时间。
@Component
public class RedisLock {
private static final String LOCK_KEY = "resource_lock";
private static final String LOCK_VALUE = UUID.randomUUID().toString();
private static final long EXPIRE_SECONDS = 10;
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 尝试加锁
*/
public boolean tryLock() {
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(LOCK_KEY, LOCK_VALUE, EXPIRE_SECONDS, TimeUnit.SECONDS);
return Boolean.TRUE.equals(locked);
}
/**
* 释放锁(简单版,生产环境请用 Lua 脚本保原子性)
*/
public void unlock() {
String currentValue = redisTemplate.opsForValue().get(LOCK_KEY);
if (LOCK_VALUE.equals(currentValue)) {
redisTemplate.delete(LOCK_KEY);
}
}
}
注解
-
1. 唯一 value 防止误删别人的锁。
-
2. 过期时间 防宕机死锁。
-
3. Lua 脚本 删锁原子性升级,留给读者做功课。
小结
|
场景 |
数据结构 |
核心命令 |
一句话总结 |
|
商品缓存 | String |
set / get |
缓存穿透、雪崩一把梭 |
|
点赞计数 | String |
incr / decr |
并发安全,一行代码 |
|
消息队列 | List |
lpush / rpop |
轻量 MQ,无 Kafka 也能飞 |
|
分布式锁 | String |
setIfAbsent / delete |
抢资源必备,保原子性 |
更多推荐




所有评论(0)