Redisson详解:高性能redis客户端,超详细!
一、Redisson介绍
Redisson是一个在Redis基础上实现的Java驻内存数据网格。它不仅提供了一系列的分布式和可扩展的Java数据结构,还提供了许多分布式服务。Redisson作为Redis的Java客户端,不仅仅是一个简单的Redis连接池,而是一个功能丰富的分布式和可扩展的Java数据结构集合。
Redisson的主要特点包括:
- 基于Netty框架实现,支持异步和同步操作
- 提供了分布式和可扩展的Java数据结构
- 内置高性能分布式缓存解决方案
- 支持Redis的多种部署模式(单机、主从、哨兵、集群)
- 内置了多种分布式锁实现
- 提供了丰富的分布式服务(如分布式调度任务、分布式MapReduce等)
二、Redisson的核心特性
分布式对象
Redisson提供了多种分布式对象,这些对象在Redis中都有对应的实现:
// 获取Redisson客户端实例
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);// 分布式对象示例
RList<String> list = redisson.getList("myList"); // 分布式List
RSet<String> set = redisson.getSet("mySet"); // 分布式Set
RMap<String, String> map = redisson.getMap("myMap"); // 分布式Map
RBucket<String> bucket = redisson.getBucket("myBucket"); // 分布式Bucket
三、Redisson缓存存储详解
Redisson提供了强大的分布式缓存解决方案,包括多种缓存策略、缓存加载机制和缓存事件监听等功能。
1. 基本缓存操作(RBucket)
RBucket是Redisson中最基本的缓存存储单元,用于存储单个对象:
// 获取Bucket对象
RBucket<User> userBucket = redisson.getBucket("user:1001");// 存储对象到缓存
User user = new User(1001, "张三", "zhangsan@example.com");
userBucket.set(user);// 设置过期时间(1小时后过期)
userBucket.set(user, 1, TimeUnit.HOURS);// 从缓存获取对象
User cachedUser = userBucket.get();
System.out.println("从缓存获取用户: " + cachedUser);// 删除缓存
userBucket.delete();// 检查缓存是否存在
boolean exists = userBucket.isExists();
2. 分布式Map缓存(RMapCache)
RMapCache是带有过期功能的分布式Map,适合用作缓存存储:
// 获取带过期功能的Map
RMapCache<String, User> userMapCache = redisson.getMapCache("userMapCache");// 存储对象并设置过期时间(30分钟后过期)
User user1 = new User(1001, "张三", "zhangsan@example.com");
userMapCache.put("1001", user1, 30, TimeUnit.MINUTES);// 存储对象并设置最大空闲时间(10分钟内没有被访问则过期)
User user2 = new User(1002, "李四", "lisi@example.com");
userMapCache.put("1002", user2, 1, TimeUnit.HOURS, 10, TimeUnit.MINUTES);// 获取对象
User cachedUser = userMapCache.get("1001");
if (cachedUser != null) {System.out.println("从缓存获取用户: " + cachedUser);
}// 获取所有键
Collection<String> keys = userMapCache.keySet();// 移除特定键
userMapCache.remove("1002");// 清空缓存
userMapCache.clear();
3. 缓存加载器(自动加载)
Redisson支持通过CacheLoader自动加载缓存,当缓存不存在时自动从数据源加载:
// 创建带缓存加载器的MapCache
RMapCache<String, User> userMapCache = redisson.getMapCache("userMapCache");// 模拟从数据库加载用户数据
CacheLoader<String, User> loader = key -> {System.out.println("从数据库加载用户: " + key);// 这里应该是从数据库查询的逻辑if ("1001".equals(key)) {return new User(1001, "张三", "zhangsan@example.com");} else if ("1002".equals(key)) {return new User(1002, "李四", "lisi@example.com");}return null;
};// 获取对象,如果不存在则自动加载
User user = userMapCache.getOrDefault("1001", loader);
System.out.println("获取用户: " + user);// 再次获取,这次会从缓存读取
User cachedUser = userMapCache.getOrDefault("1001", loader);
System.out.println("再次获取用户(应来自缓存): " + cachedUser);
4. 多级缓存策略
Redisson可以与本地缓存结合实现多级缓存:
// 本地缓存(Caffeine示例)
Cache<String, User> localCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES) // 本地缓存1分钟.maximumSize(1000).build();// Redis分布式缓存
RMapCache<String, User> redisCache = redisson.getMapCache("userCache");// 多级缓存获取
public User getUserWithMultiLevelCache(String userId) {// 1. 先查本地缓存User user = localCache.getIfPresent(userId);if (user != null) {System.out.println("从本地缓存获取用户: " + userId);return user;}// 2. 查Redis分布式缓存user = redisCache.get(userId);if (user != null) {System.out.println("从Redis缓存获取用户: " + userId);// 回填本地缓存localCache.put(userId, user);return user;}// 3. 查数据库(模拟)System.out.println("从数据库加载用户: " + userId);user = loadFromDatabase(userId);if (user != null) {// 写入Redis缓存(设置30分钟过期)redisCache.put(userId, user, 30, TimeUnit.MINUTES);// 写入本地缓存localCache.put(userId, user);}return user;
}// 模拟数据库加载
private User loadFromDatabase(String userId) {// 实际应用中这里是从数据库查询if ("1001".equals(userId)) {return new User(1001, "张三", "zhangsan@example.com");}return null;
}
5. 缓存事件监听
Redisson支持监听缓存事件,如缓存添加、移除等:
// 获取MapCache
RMapCache<String, User> userMapCache = redisson.getMapCache("userMapCache");// 添加缓存事件监听器
userMapCache.addListener(new EntryAddedListener<String, User>() {@Overridepublic void onCreated(EntryEvent<String, User> event) {System.out.println("缓存添加事件 - Key: " + event.getKey() + ", Value: " + event.getValue());}
});userMapCache.addListener(new EntryRemovedListener<String, User>() {@Overridepublic void onRemoved(EntryEvent<String, User> event) {System.out.println("缓存移除事件 - Key: " + event.getKey() + ", Value: " + event.getValue());}
});// 触发事件
userMapCache.put("1001", new User(1001, "张三", "zhangsan@example.com"));
userMapCache.remove("1001");
6. 缓存统计信息
Redisson提供了缓存统计功能,可以监控缓存命中率等指标:
// 获取带统计功能的MapCache
RMapCache<String, User> statsMapCache = redisson.getMapCache("statsMapCache");// 启用统计(需要Redisson配置中启用)
// statsMapCache = redisson.getMapCache("statsMapCache",
// new MapOptions<String, User>().statisticsEnabled(true));// 存储数据
statsMapCache.put("1001", new User(1001, "张三", "zhangsan@example.com"));// 注意:获取统计信息需要通过Redis命令或管理工具
// 实际应用中可以通过Redis的INFO命令或Redisson的管理API获取
四、Redisson缓存高级特性
1. 缓存预热
在应用启动时预先加载热点数据到缓存:
@PostConstruct
public void initCache() {// 应用启动时预热热门用户数据List<String> hotUserIds = Arrays.asList("1001", "1002", "1003");for (String userId : hotUserIds) {User user = loadFromDatabase(userId);if (user != null) {userMapCache.put(userId, user, 2, TimeUnit.HOURS);}}
}
2. 缓存雪崩防护
通过为不同的缓存项设置随机的过期时间,避免大量缓存同时失效:
// 为不同的用户设置基础过期时间+随机偏移量,避免雪崩
public void cacheUserWithAvalancheProtection(User user) {long baseTtl = 30; // 基础30分钟long randomOffset = ThreadLocalRandom.current().nextLong(0, 10); // 随机0-10分钟偏移long ttl = baseTtl + randomOffset;userMapCache.put(user.getId().toString(), user, ttl, TimeUnit.MINUTES);
}
3. 缓存穿透防护
对于不存在的key也进行缓存,避免频繁查询数据库:
public User getUserWithPenetrationProtection(String userId) {// 1. 先查缓存User user = userMapCache.get(userId);if (user != null) {// 缓存命中,如果是特殊标记的空值,返回nullif (user instanceof NullUser) {return null;}return user;}// 2. 查数据库user = loadFromDatabase(userId);if (user != null) {// 3. 数据库存在,写入缓存userMapCache.put(userId, user, 30, TimeUnit.MINUTES);} else {// 4. 数据库不存在,缓存空值防止穿透userMapCache.put(userId, new NullUser(), 5, TimeUnit.MINUTES);}return user;
}// 空值标记类
private static class NullUser extends User {public NullUser() {super(-1, null, null);}
}
4. 缓存击穿防护(互斥锁)
使用分布式锁防止热点key失效时大量请求直接打到数据库:
public User getUserWithBreakdownProtection(String userId) {String lockKey = "user_lock:" + userId;RLock lock = redisson.getLock(lockKey);try {// 1. 先查缓存User user = userMapCache.get(userId);if (user != null) {if (user instanceof NullUser) {return null;}return user;}// 2. 获取分布式锁boolean locked = lock.tryLock(1, 10, TimeUnit.SECONDS);if (locked) {try {// 双重检查,可能在等待锁的过程中其他线程已经加载了缓存user = userMapCache.get(userId);if (user != null) {if (user instanceof NullUser) {return null;}return user;}// 3. 查数据库user = loadFromDatabase(userId);if (user != null) {// 4. 写入缓存userMapCache.put(userId, user, 30, TimeUnit.MINUTES);} else {// 5. 缓存空值userMapCache.put(userId, new NullUser(), 5, TimeUnit.MINUTES);}return user;} finally {lock.unlock();}} else {// 获取锁失败,短暂等待后重试Thread.sleep(100);return getUserWithBreakdownProtection(userId);}} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException("获取用户信息被中断", e);}
}
五、Redisson配置详解(补充缓存相关配置)
1. 缓存配置选项
Config config = new Config();// 单机模式配置
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("password");// 缓存相关配置(通过MapOptions设置)
MapOptions<String, User> mapOptions = MapOptions.<String, User>defaults().evictionPolicy(EvictionPolicy.LRU) // 淘汰策略: LRU, LFU, FIFO.maxSize(1000) // 最大缓存条目数.timeToLive(30, TimeUnit.MINUTES) // 条目存活时间.maxIdle(10, TimeUnit.MINUTES); // 条目最大空闲时间// 创建带配置的MapCache
RMapCache<String, User> userMapCache = redisson.getMapCache("userMapCache", mapOptions);
2. 淘汰策略
Redisson支持多种缓存淘汰策略:
// LRU (最近最少使用)
MapOptions<String, User> lruOptions = MapOptions.<String, User>defaults().evictionPolicy(EvictionPolicy.LRU);// LFU (最不经常使用)
MapOptions<String, User> lfuOptions = MapOptions.<String, User>defaults().evictionPolicy(EvictionPolicy.LFU);// FIFO (先进先出)
MapOptions<String, User> fifoOptions = MapOptions.<String, User>defaults().evictionPolicy(EvictionPolicy.FIFO);
集群配置:
1.单机模式
Config config = new Config();// 单机模式
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("password").setDatabase(0).setConnectionPoolSize(64) // 连接池大小.setConnectionMinimumIdleSize(10) // 最小空闲连接数.setIdleConnectionTimeout(10000) // 空闲连接超时时间.setConnectTimeout(10000) // 连接超时时间.setTimeout(3000) // 命令等待超时时间.setRetryAttempts(3) // 命令重试次数.setRetryInterval(1500) // 命令重试发送时间间隔.setPingConnectionInterval(30000) // 连接空闲多久后发送ping命令保持连接.setKeepAlive(true); // 是否保持长连接RedissonClient redisson = Redisson.create(config);
2. 主从模式配置
Config config = new Config();
config.useMasterSlaveServers().setMasterAddress("redis://127.0.0.1:6379").addSlaveAddress("redis://127.0.0.1:6380", "redis://127.0.0.1:6381").setPassword("password").setDatabase(0).setSlaveConnectionPoolSize(64).setMasterConnectionPoolSize(64).setReadMode(ReadMode.SLAVE) // 读操作从从节点读取.setSubscriptionMode(SubscriptionMode.SLAVE); // 订阅操作从从节点读取RedissonClient redisson = Redisson.create(config);
3. 哨兵模式配置
Config config = new Config();
config.useSentinelServers().setMasterName("mymaster").addSentinelAddress("redis://127.0.0.1:26379", "redis://127.0.0.1:26380").setPassword("password").setDatabase(0).setMasterConnectionPoolSize(64).setSlaveConnectionPoolSize(64);RedissonClient redisson = Redisson.create(config);
4. 集群模式配置
Config config = new Config();
config.useClusterServers().addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001").addNodeAddress("redis://127.0.0.1:7002", "redis://127.0.0.1:7003").addNodeAddress("redis://127.0.0.1:7004", "redis://127.0.0.1:7005").addNodeAddress("redis://127.0.0.1:7006", "redis://127.0.0.1:7007").setPassword("password").setScanInterval(2000) // 集群状态扫描间隔时间.setSlaveConnectionPoolSize(64).setMasterConnectionPoolSize(64);RedissonClient redisson = Redisson.create(config);
六、Redisson缓存最佳实践
1. 缓存设计原则
- 合理设置缓存粒度:根据业务需求确定缓存对象的大小和粒度
- 选择合适的过期策略:根据数据特性设置合理的TTL和最大空闲时间
- 避免大Key:单个缓存值不宜过大,建议控制在10MB以内
- 考虑数据一致性:明确缓存与数据库的一致性要求
2. 性能优化建议
- 批量操作:尽可能使用批量操作减少网络往返
- 异步操作:对于非关键路径使用异步缓存操作
- 本地缓存结合:热点数据可结合本地缓存实现多级缓存
- 监控缓存命中率:定期分析缓存命中率,优化缓存策略
3. 监控与维护
- 监控缓存指标:关注缓存大小、命中率、淘汰率等指标
- 定期清理:对于长期不用的缓存数据定期清理
- 容量规划:根据业务增长预测缓存容量需求
Redisson不仅提供了强大的分布式数据结构支持,还通过其分布式缓存解决方案(如RBucket、RMapCache等)为Java应用提供了高性能、易用的缓存存储能力。通过本文的介绍,我们深入了解了Redisson的缓存存储功能,包括:
- 基本缓存操作:通过RBucket实现简单的键值缓存
- 高级缓存功能:通过RMapCache实现带过期策略的分布式Map缓存
- 缓存加载机制:自动从数据源加载缓存的CacheLoader
- 多级缓存策略:结合本地缓存实现高效的多级缓存
- 缓存事件监听:监听缓存变化事件
- 缓存保护机制:防止缓存雪崩、穿透、击穿等问题的策略