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. 1. 前缀设计 product:,可读性高,方便批量删除。

  2. 2. 过期时间 60 秒,既防雪崩又保热数据。

  3. 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. 1. 原子自增 increment 保证并发安全,一行代码顶 100 行 Java 锁。

  2. 2. 前缀动态拼接 方便统计某条动态。

  3. 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. 1. 左进右出 保序,天然 FIFO。

  2. 2. 非阻塞 / 阻塞双模式 适配不同业务节奏。

  3. 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. 1. 唯一 value 防止误删别人的锁。

  2. 2. 过期时间 防宕机死锁。

  3. 3. Lua 脚本 删锁原子性升级,留给读者做功课。

小结

场景

数据结构

核心命令

一句话总结

商品缓存

String

set / get

缓存穿透、雪崩一把梭

点赞计数

String

incr / decr

并发安全,一行代码

消息队列

List

lpush / rpop

轻量 MQ,无 Kafka 也能飞

分布式锁

String

setIfAbsent / delete

抢资源必备,保原子性

更多推荐