1. 依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.28.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2. Redisson配置
2.1 基本配置
@Slf4j
@Configuration
public class RedissonConfig {
/**
* redisson协议前缀
*/
private static final String SCHEMA_PREFIX = "redis://";
/**
* 锁超时时间
*/
private long lockWatchTimeOut = 30000;
@Bean
public RedissonClient redissonClient(RedisProperties redisProperties) {
Config config = new Config();
RedisProperties.Sentinel sentinel = redisProperties.getSentinel();
RedisProperties.Cluster redisPropertiesCluster = redisProperties.getCluster();
if (redisPropertiesCluster != null) {
//集群redis
ClusterServersConfig clusterServersConfig = config.useClusterServers();
for (String cluster : redisPropertiesCluster.getNodes()) {
clusterServersConfig.addNodeAddress(SCHEMA_PREFIX + cluster);
}
if (StringUtils.hasText(redisProperties.getPassword())) {
clusterServersConfig.setPassword(redisProperties.getPassword());
}
// clusterServersConfig.setTimeout((int) redisProperties.getTimeout().toMillis());
clusterServersConfig.setPingConnectionInterval(30000);
} else if (StringUtils.hasText(redisProperties.getHost())) {
//单点redis
SingleServerConfig singleServerConfig = config.useSingleServer().
setAddress(SCHEMA_PREFIX + redisProperties.getHost() + ":" + redisProperties.getPort());
if (StringUtils.hasText(redisProperties.getPassword())) {
singleServerConfig.setPassword(redisProperties.getPassword());
}
// singleServerConfig.setTimeout((int) redisProperties.getTimeout().toMillis());
singleServerConfig.setPingConnectionInterval(30000);
singleServerConfig.setDatabase(redisProperties.getDatabase());
} else if (sentinel != null) {
//哨兵模式
SentinelServersConfig sentinelServersConfig = config.useSentinelServers();
sentinelServersConfig.setMasterName(sentinel.getMaster());
for (String node : sentinel.getNodes()) {
sentinelServersConfig.addSentinelAddress(SCHEMA_PREFIX + node);
}
if (StringUtils.hasText(redisProperties.getPassword())) {
sentinelServersConfig.setPassword(redisProperties.getPassword());
}
// sentinelServersConfig.setTimeout((int) redisProperties.getTimeout().toMillis());
sentinelServersConfig.setPingConnectionInterval(30000);
sentinelServersConfig.setDatabase(redisProperties.getDatabase());
}
config.setLockWatchdogTimeout(lockWatchTimeOut);
return Redisson.create(config);
}
}
2.2 使用
@Autowired
private RedissonClient redissonClient;
// 获取锁
RLock rlock = redissonClient.getLock(this.getClass().toString());
boolean lock = rlock.tryLock();
// 释放锁
lock.unlock();
3. Redis配置
3.1 基本配置
@Slf4j
@Configuration
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {
@Bean
@Primary
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
RedisSerializerUtil.setRedisSerializer(redisTemplate);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedisService redisService(RedisTemplate<String, Object> redisTemplate) {
return new RedisService(redisTemplate);
}
}
3.2 可选数据库配置
有时候我们使用的缓存不一定在同一个数据库,所以有了这个配置
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisHelper {
private final RedisProperties redisProperties;
public RedisHelper(RedisProperties redisProperties) {
this.redisProperties = redisProperties;
}
ConcurrentHashMap<Integer, RedisTemplate<String, Object>> templateMap = new ConcurrentHashMap<>();
public RedisService database(Integer database) {
if (database < 0 || database > 15) throw new CacheException("redis数据库配置错误!");
RedisTemplate<String, Object> redisTemplate;
if (templateMap.containsKey(database)) {
redisTemplate = templateMap.get(database);
} else {
redisTemplate = RedisTemplateFactory.createRedisTemplate(redisProperties.getHost(), redisProperties.getPort(), redisProperties.getPassword(), database);
RedisSerializerUtil.setRedisSerializer(redisTemplate);
templateMap.put(database, redisTemplate);
}
return new RedisService(redisTemplate);
}
}
public class RedisTemplateFactory {
public static RedisTemplate<String, Object> createRedisTemplate(String host, Integer port, String password, Integer database) {
return createRedisTemplate(host, port, password, database, 8, 8, -1L, 0);
}
public static RedisTemplate<String, Object> createRedisTemplate(String host, Integer port, String password, Integer database, Integer maxActive, Integer maxIdle, Long maxWait, Integer minIdle) {
GenericObjectPoolConfig poolConfig = localPoolConfig(maxActive, maxIdle, maxWait, minIdle);
RedisStandaloneConfiguration redisConfig = localRedisConfig(host, port, password, database);
LettuceConnectionFactory connectionFactory = localLettuceConnectionFactory(redisConfig, poolConfig);
return localRedisTemplate(connectionFactory);
}
/**
* 连接池属性
*
* @param maxActive
* @param maxIdle
* @param maxWait
* @param minIdle
* @return
*/
public static GenericObjectPoolConfig localPoolConfig(Integer maxActive, Integer maxIdle, Long maxWait, Integer minIdle) {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWait);
return config;
}
/**
* Redis配置
*
* @param host
* @param port
* @param password
* @param database
* @return
*/
public static RedisStandaloneConfiguration localRedisConfig(String host, Integer port, String password, Integer database) {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPassword(RedisPassword.of(password));
config.setPort(port);
config.setDatabase(database);
return config;
}
/**
* 根据Lettuce连接工厂创建RedisTemplate
*
* @param localLettuceConnectionFactory
* @return
*/
public static RedisTemplate<String, Object> localRedisTemplate(LettuceConnectionFactory localLettuceConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(localLettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 根据 连接池配置、Redis 配置创建连接工厂
*
* @param localRedisConfig
* @param localPoolConfig
* @return
*/
public static LettuceConnectionFactory localLettuceConnectionFactory(RedisStandaloneConfiguration localRedisConfig, GenericObjectPoolConfig localPoolConfig) {
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100)).poolConfig(localPoolConfig).build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(localRedisConfig, clientConfig);
factory.afterPropertiesSet();
return factory;
}
}
3.3 注入RedisService
public class RedisService {
public final RedisTemplate redisTemplate;
public RedisService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 查找key
* redisTemplate的opsForHash,opsForSet,opsForZSet 可以 分别对应 sscan、hscan、zscan
*
* @param matchKey
* @return
*/
public Set<String> scan(String matchKey) {
return (HashSet<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
HashSet<String> hashSet = new HashSet<>();
Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(matchKey).build());
while (cursor.hasNext()) {
byte[] next = cursor.next();
String s = new String(next);
hashSet.add(s);
}
return hashSet;
});
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获取有效时间
*
* @param key Redis键
* @return 有效时间
*/
public long getExpire(final String key) {
return redisTemplate.getExpire(key);
}
// 普通对象
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false 失败
*/
public boolean setNx(String key, Object value) {
return redisTemplate.opsForValue().setIfPresent(key, value);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setNx(String key, Object value, long time) {
return redisTemplate.opsForValue().setIfPresent(key, value, time, TimeUnit.SECONDS);
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long increment(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decrement(String key, long delta) {
return redisTemplate.opsForValue().decrement(key, -delta);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param time 时间
*/
public <T> void setObject(final String key, final T value, final long time) {
redisTemplate.opsForValue().set(key, value);
if (time > 0) {
expire(key, time);
}
}
/**
* 判断 key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean delObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public boolean delObject(final Collection collection) {
return redisTemplate.delete(collection) > 0;
}
// list类型
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param list 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setList(final String key, final List<T> list) {
Long count = redisTemplate.opsForList().rightPushAll(key, list);
return count == null ? 0 : count;
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param list 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setList(final String key, final List<T> list, final long time) {
Long count = redisTemplate.opsForList().rightPushAll(key, list);
if (time > 0) {
expire(key, time);
}
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 获得缓存的list对象
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1 代表所有值
* @return
*/
public List<Object> getList(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long getListSize(String key) {
return redisTemplate.opsForList().size(key);
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public <T> T getIndexList(String key, long index) {
return (T) redisTemplate.opsForList().index(key, index);
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public <T> void updateIndexList(String key, long index, T value) {
redisTemplate.opsForList().set(key, index, value);
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public <T> long delList(String key, long count, T value) {
return redisTemplate.opsForList().remove(key, count, value);
}
// set类型
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setSetValue(final String key, final Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
for (T t : dataSet) {
setOperation.add(t);
}
return setOperation;
}
/**
* 缓存Set
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long setSetAndTime(String key, long time, Object... values) {
long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getSetValue(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean hasSetKeyValue(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long getSetSize(String key) {
return redisTemplate.opsForSet().size(key);
}
/**
* 删除set的值
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long delSetValues(String key, Object... values) {
return redisTemplate.opsForSet().remove(key, values);
}
// zSet 有序集合
/**
* 添加有序集合
*
* @param key
* @param score
* @param val
* @param time
*/
public void setZSetValue(String key, Object val, double score, long time) {
redisTemplate.opsForZSet().add(key, val, score);
this.expire(key, time);
}
/**
* 取出所有有序集合,进行降序排序
*
* @param key
* @return
*/
public Set<Object> getZSetValue(String key) {
return redisTemplate.opsForZSet().reverseRange(key, 0, -1);
}
/**
* 取出部分有序集合,进行降序排序
*
* @param key
* @return
*/
public Set<Object> getZSetValue(String key, Integer start, Integer end) {
return redisTemplate.opsForZSet().reverseRange(key, start, end);
}
/**
* 获取zSet总条数
*
* @param key
*/
public long getZSetSize(String key) {
return redisTemplate.opsForZSet().zCard(key);
}
/**
* 增量,若key不存在则新建并添加数据,否则累加
*
* @param key
* @param val
* @param score
* @param time
*/
public void incrementZSetScore(String key, Object val, double score, long time) {
redisTemplate.opsForZSet().incrementScore(key, val, score);
this.expire(key, time);
}
// map类型
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setHashMap(final String key, final Map<String, T> dataMap) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setHashMap(final String key, final Map<String, T> dataMap, final long time) {
redisTemplate.opsForHash().putAll(key, dataMap);
if (time > 0) {
expire(key, time);
}
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setHashValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
* @param time 时间 秒
*/
public <T> void setHashValue(final String key, final String hKey, final T value, final long time) {
redisTemplate.opsForHash().put(key, hKey, value);
if (time > 0) {
expire(key, time);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getHashMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getHashValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiHashValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean delHashValue(final String key, final String hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean delHashValues(final String key, final Object... hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 判断hash表中是否有该项的值
*
* @param key redis键
* @param hKey hash键
* @return true 存在 false不存在
*/
public boolean hasHashKey(String key, String hKey) {
return redisTemplate.opsForHash().hasKey(key, hKey);
}
/**
* hash递增
*
* @param key 键
* @param hKey 项
* @param value 要增加的值(大于0)
* @return
*/
public double incrementHash(String key, String hKey, double value) {
return redisTemplate.opsForHash().increment(key, hKey, value);
}
}
3.4 使用
// 直接使用
private RedisService redisService;
// 切换数据库
@Autowired
private RedisHelper redisHelper;
Boolean boolean = redisHelper.database(1).hasKey("keyName");
3.5 yaml
# spring配置
spring:
redis:
host: localhost
port: 6379
timeout: 180000 # 连接超时时间(毫秒)
database: 0 # Redis默认情况下有16个分片,这里配置具体使用的分片
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制) 默认 8
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-idle: 8 # 连接池中的最大空闲连接 默认 8
min-idle: 0 # 连接池中的最小空闲连接 默认 0