redis-cache
SKILL.md
Redis 缓存开发指南
快速索引
| 功能 | 工具类/注解 | 说明 |
|---|---|---|
| 对象缓存 | RedissonClient / [你的RedisUtils] |
基于 Redisson |
| Spring Cache | @Cacheable/@CachePut/@CacheEvict |
声明式缓存 |
| 分布式锁 | redissonClient.getLock() |
需注入 RedissonClient |
| 限流控制 | Redisson RRateLimiter |
基于 Redisson |
| 原子操作 | Redisson RAtomicLong |
原子递增/递减 |
| 发布订阅 | Redisson RTopic |
消息通信 |
一、Redisson 基础操作
1.1 基础缓存操作
import org.redisson.api.RedissonClient;
import org.redisson.api.RBucket;
@Service
@RequiredArgsConstructor
public class CacheService {
private final RedissonClient redissonClient;
// 设置缓存
public void set(String key, Object value, Duration ttl) {
RBucket<Object> bucket = redissonClient.getBucket(key);
bucket.set(value, ttl);
}
// 获取缓存
public <T> T get(String key) {
RBucket<T> bucket = redissonClient.getBucket(key);
return bucket.get();
}
// 删除缓存
public boolean delete(String key) {
return redissonClient.getBucket(key).delete();
}
// 判断是否存在
public boolean exists(String key) {
return redissonClient.getBucket(key).isExists();
}
// 不存在时设置(原子操作)
public boolean setIfAbsent(String key, Object value, Duration ttl) {
RBucket<Object> bucket = redissonClient.getBucket(key);
return bucket.trySet(value, ttl);
}
}
1.2 集合操作
// List
RList<String> list = redissonClient.getList("myList");
list.addAll(dataList);
List<String> result = list.readAll();
// Set
RSet<String> set = redissonClient.getSet("mySet");
set.addAll(dataSet);
Set<String> result = set.readAll();
// Map
RMap<String, Object> map = redissonClient.getMap("myMap");
map.putAll(dataMap);
map.put("key3", "value3");
Object value = map.get("key1");
1.3 发布订阅
// 发布消息
RTopic topic = redissonClient.getTopic("notification:channel");
topic.publish(messageObj);
// 订阅消息
RTopic topic = redissonClient.getTopic("notification:channel");
topic.addListener(MessageDTO.class, (channel, msg) -> {
// 处理消息
});
1.4 限流控制
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateType;
import org.redisson.api.RateIntervalUnit;
RRateLimiter limiter = redissonClient.getRateLimiter("api:limit:user:" + userId);
// 每10秒最多100个请求
limiter.trySetRate(RateType.OVERALL, 100, 10, RateIntervalUnit.SECONDS);
if (!limiter.tryAcquire()) {
throw new [你的异常类]("请求过于频繁");
}
1.5 原子操作
RAtomicLong counter = redissonClient.getAtomicLong("counter:view");
counter.set(0L);
long value = counter.get();
long newVal = counter.incrementAndGet();
long newVal = counter.decrementAndGet();
二、Spring Cache 注解使用规范
@Cacheable - 查询缓存
@Cacheable(value = "dictData", key = "#dictType")
@Override
public List<DictDataVo> listDictDataByType(String dictType) {
if (dictType == null || dictType.isBlank()) {
return Collections.emptyList();
}
List<DictData> dictDataList = dictDataMapper.selectByType(dictType);
if (dictDataList.isEmpty()) {
return Collections.emptyList(); // 返回空列表防止缓存穿透
}
return dictDataList.stream()
.map(d -> BeanUtil.copyProperties(d, DictDataVo.class))
.toList();
}
@CachePut / @CacheEvict
@CachePut(value = "dictData", key = "#bo.dictType")
public List<DictDataVo> insertDictType(DictTypeBo bo) { ... }
@CacheEvict(value = "dictData", key = "#dictType")
public void deleteDictType(String dictType) { ... }
@CacheEvict(value = "dictData", allEntries = true)
public void clearAllDictCache() { ... }
返回值禁止使用不可变集合
// ❌ 禁止! @Cacheable 返回值序列化失败
return List.of(data1, data2);
return Set.of("admin", "user");
return Map.of("key1", "value1");
// ✅ 正确:使用可变集合
List<DictDataVo> result = new ArrayList<>();
result.add(data1);
return result;
三、CacheNames 命名规范
推荐格式
cacheNames#ttl#maxIdleTime#maxSize
- ttl: 过期时间(0=不过期,默认0)
- maxIdleTime: 最大空闲时间(0=不检测,默认0)
- maxSize: 最大条数(0=无限,默认0)
"test#60s" // 60秒过期
"test#0#60s" // 不过期,60秒空闲清理
"test#0#1m#1000" // 不过期,1分钟空闲,最大1000条
"test#1h#0#500" // 1小时过期,最大500条
常量定义示例
public interface CacheNames {
String SYS_CONFIG = "sys_config";
String SYS_DICT = "sys_dict";
String SYS_USER_NAME = "sys_user_name#30d";
String SYS_DEPT = "sys_dept#30d";
}
四、分布式锁
直接注入
RedissonClient使用。
@Service
@RequiredArgsConstructor
public class OrderServiceImpl {
private final RedissonClient redissonClient;
public void submitOrder(OrderBo orderBo) {
String lockKey = "lock:submit:order:" + orderBo.getUserId();
RLock lock = redissonClient.getLock(lockKey);
try {
boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
if (!locked) {
throw new [你的异常类]("请勿重复提交订单");
}
try {
orderMapper.insert(orderBo);
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock(); // 必须在 finally 中释放
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new [你的异常类]("订单提交被中断");
}
}
}
五、缓存 Key 命名规范
格式:{业务模块}:{功能}:{具体标识}
示例:
user:info:123 user:roles:123 user:permissions:123
dict:data:sys_user_sex order:info:20240101001 order:status:20240101001
lock:order:20240101001 lock:stock:123 lock:submit:order:456
limit:api:user:123 limit:sms:18888888888
六、注意事项速查
- @Cacheable 返回值不能使用不可变集合(List.of()、Set.of()、Map.of())
- 分布式锁必须在 finally 中释放
- 返回空列表而不是 null,防止缓存穿透
- 设置随机过期时间偏移,避免缓存雪崩
- 热点数据用分布式锁 + 双重检查,防止缓存击穿
- keys() 模式匹配要谨慎,生产环境避免大范围扫描
Weekly Installs
4
Repository
xu-cell/ai-engi…ing-initGitHub Stars
9
First Seen
9 days ago
Security Audits
Installed on
gemini-cli4
github-copilot4
codex4
kimi-cli4
cursor4
amp4