Redis 使用实践

Redis 有以下经典实用场景:

  • 缓存系统:加速热点数据访问(如电商商品详情页)
  • 分布式锁:利用 SET NX 命令实现分布式同步

  • 实时统计:计数器、UV 统计、在线用户数

  • 消息队列:基于 List 的阻塞队列(BLPOP/BLPUSH)

  • 实时分析:结合 Bitmap 和 HyperLogLog 做用户行为分析

还有其他 Redis 相关实践,例如 Lua 脚本的使用、选择部署模式(单示例、主从、Cluster)不在此列。

Redis 作为缓存系统实践案例

CoTrip项目中对热点数据进行了缓存,对用户的行程信息做了缓存,大幅提高进入“我的行程”页面时的响应速度。

还对 baiduAPI 的调用结果做了缓存……原因有两个,调用第三方 API 比较耗时,还有就是超额度了要收费,所以这里加上的缓存是不过期的,长期保存在 Redis 中的,毕竟是个学校作业的项目,也不想因为每次刷新一下就调 API 然后超额度。这主要出于成本考虑的。

由于服务器配置不高(2核2G磁盘40G),运行个MySQL+Redis+Minio已经极限了,完全没法再运行个jar包甚至加上前端了……除非再买一条服务器(正好阿里云一台、腾讯云一台…也行(?))

Redis 作为分布式锁实践案例

在某线上学习项目中(业务代码不便开源),存在多个服务实例同时操作同一份共享资源的场景,例如:
一件商品被多个用户同时下单购买、库存量的变化。

为避免并发条件下的数据不一致问题,引入了 Redis 分布式锁 进行控制。

为什么选择 Redis + Redisson

相比手动使用 SETNX 实现分布式锁,Redisson 提供了更完整的封装:

  • 自动处理锁的原子性
  • 支持可重入锁
  • 内置 WatchDog 机制,避免锁误释放
  • 接口语义接近本地 ReentrantLock,降低使用成本

核心代码示例

以下为简化后的示例代码,用于说明核心使用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

RLock lock = redissonClient.getLock(lockKey);
lock.lock();

try {
// 访问或修改共享资源的业务逻辑
} catch (Exception e) {
// 异常处理
} finally {
lock.unlock();
}

关键实现说明

  • lock.lock()
    • 默认是阻塞获取锁
    • 使用 Redisson 的 WatchDog 机制自动续期
    • 只要线程存活且未释放锁,锁不会因过期被误删
  • finally 中释放锁
    • 保证业务异常情况下锁能够被正确释放
    • 避免死锁风险
  • lockKey 的设计
    • 锁粒度应尽量细
    • 通常由业务唯一标识(如用户 ID、资源 ID)组成

该方式在项目中有效避免了并发写入导致的数据覆盖问题,同时保持了较低的实现复杂度。