一、设置
1.1 引入maven
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.17.0</version></dependency>1.2 设置文件
spring.redis.database=0spring.redis.password=spring.redis.timeout=3000#sentinel/cluster/singlespring.redis.mode=single#毗连池设置spring.redis.pool.max-idle=16spring.redis.pool.min-idle=8spring.redis.pool.max-active=8spring.redis.pool.max-wait=3000spring.redis.pool.conn-timeout=3000spring.redis.pool.so-timeout=3000spring.redis.pool.size=10#单机设置spring.redis.single.address=192.168.60.23:6379#集群设置spring.redis.cluster.scan-interval=1000spring.redis.cluster.nodes=spring.redis.cluster.read-mode=SLAVEspring.redis.cluster.retry-attempts=3spring.redis.cluster.failed-attempts=3spring.redis.cluster.slave-connection-pool-size=64spring.redis.cluster.master-connection-pool-size=64spring.redis.cluster.retry-interval=1500#哨兵设置spring.redis.sentinel.master=business-masterspring.redis.sentinel.nodes=spring.redis.sentinel.master-onlyWrite=truespring.redis.sentinel.fail-max=31.3 设置文件读取
/** * @author: huangyibo * @Date: 2022/6/23 10:56 * @Description: 设置文件读取 */@ConfigurationProperties(prefix="spring.redis", ignoreUnknownFields = false)@Data@ToStringpublic class RedisProperties { private int database; /** * 等候节点复兴下令的时间。该时间从下令发送乐成时开始计时 */ private int timeout; private String password; private String mode; /** * 池设置 */ private RedisPoolProperties pool; /** * 单机信息设置 */ private RedisSingleProperties single; /** * 集群 信息设置 */ private RedisClusterProperties cluster; /** * 哨兵设置 * */ private RedisSentinelProperties sentinel;}/** * @author: huangyibo * @Date: 2022/6/23 11:00 * @Description: redis 池设置 */@Data@ToStringpublic class RedisPoolProperties { private int maxIdle; private int minIdle; private int maxActive; private int maxWait; private int connTimeout; private int soTimeout; /** * 池巨细 */ private int size;}/** * @author: huangyibo * @Date: 2022/6/23 11:02 * @Description: 单节点设置 */@Data@ToStringpublic class RedisSingleProperties { private String address;}/** * @author: huangyibo * @Date: 2022/6/23 11:03 * @Description: 集群设置 */@Data@ToStringpublic class RedisClusterProperties { /** * 集群状态扫描隔断时间,单元是毫秒 */ private int scanInterval; /** * 集群节点 */ private String nodes; /** * 默认值: SLAVE(只在从服务节点里读取)设置读取利用选择节点的模式。 可用值为: SLAVE - 只在从服务节点里读取。 * MASTER - 只在主服务节点里读取。 MASTER_SLAVE - 在主从服务节点里都可以读取 */ private String readMode; /** * (从节点毗连池巨细) 默认值:64 */ private int slaveConnectionPoolSize; /** * 主节点毗连池巨细)默认值:64 */ private int masterConnectionPoolSize; /** * (下令失败重试次数) 默认值:3 */ private int retryAttempts; /** *下令重试发送时间隔断,单元:毫秒 默认值:1500 */ private int retryInterval; /** * 实行失败最大次数默认值:3 */ private int failedAttempts;}/** * @author: huangyibo * @Date: 2022/6/23 11:06 * @Description: 哨兵设置 */@Data@ToStringpublic class RedisSentinelProperties { /** * 哨兵master 名称 */ private String master; /** * 哨兵节点 */ private String nodes; /** * 哨兵设置 */ private boolean masterOnlyWrite; /** * */ private int failMax;}1.4 CacheConfiguration
import org.redisson.Redisson;import org.redisson.api.RedissonClient;import org.redisson.config.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.util.StringUtils;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/** * @author: huangyibo * @Date: 2022/6/23 11:08 * @Description: */@Configuration@EnableConfigurationProperties(RedisProperties.class)public class CacheConfiguration { @Autowired private RedisProperties redisProperties; @Configuration @ConditionalOnClass({Redisson.class}) @ConditionalOnExpression("'${spring.redis.mode}'=='single' or '${spring.redis.mode}'=='cluster' or '${spring.redis.mode}'=='sentinel'") protected class RedissonSingleClientConfiguration { /** * 单机模式 redisson 客户端 */ @Bean @ConditionalOnProperty(name="spring.redis.mode", havingValue="single") public RedissonClient redissonSingle() { Config config = new Config(); String node = redisProperties.getSingle().getAddress(); node = node.startsWith("redis://") ? node : "redis://" + node; SingleServerConfig serverConfig = config.useSingleServer() .setAddress(node) .setTimeout(redisProperties.getPool().getConnTimeout()) .setConnectionPoolSize(redisProperties.getPool().getSize()) .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle()); if(!StringUtils.isEmpty(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } /** * 集群模式的 redisson 客户端 * * @return */ @Bean @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "cluster") public RedissonClient redissonCluster() { System.out.println("cluster redisProperties:" + redisProperties.getCluster()); Config config = new Config(); String[] nodes = redisProperties.getCluster().getNodes().split(","); List<String> newNodes = new ArrayList<>(nodes.length); Arrays.stream(nodes).forEach((index) -> newNodes.add( index.startsWith("redis://") ? index : "redis://" + index) ); ClusterServersConfig serverConfig = config.useClusterServers() .addNodeAddress(newNodes.toArray(new String[0]) ).setScanInterval( redisProperties.getCluster().getScanInterval() ).setIdleConnectionTimeout( redisProperties.getPool().getSoTimeout() ).setConnectTimeout( redisProperties.getPool().getConnTimeout() ).setRetryAttempts( redisProperties.getCluster().getRetryAttempts() ).setRetryInterval( redisProperties.getCluster().getRetryInterval() ).setMasterConnectionPoolSize( redisProperties.getCluster().getMasterConnectionPoolSize() ).setSlaveConnectionPoolSize( redisProperties.getCluster().getSlaveConnectionPoolSize() ).setTimeout( redisProperties.getTimeout() ); if (!StringUtils.isEmpty(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } /** * 哨兵模式 redisson 客户端 * @return */ @Bean @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "sentinel") public RedissonClient redissonSentinel() { System.out.println("sentinel redisProperties:" + redisProperties.getSentinel()); Config config = new Config(); String[] nodes = redisProperties.getSentinel().getNodes().split(","); List<String> newNodes = new ArrayList<>(nodes.length); Arrays.stream(nodes).forEach((index) -> newNodes.add( index.startsWith("redis://") ? index : "redis://" + index) ); SentinelServersConfig serverConfig = config.useSentinelServers() .addSentinelAddress(newNodes.toArray(new String[0])) .setMasterName(redisProperties.getSentinel().getMaster()) .setReadMode(ReadMode.SLAVE) .setTimeout(redisProperties.getTimeout()) .setMasterConnectionPoolSize(redisProperties.getPool().getSize()) .setSlaveConnectionPoolSize(redisProperties.getPool().getSize()); if (!StringUtils.isEmpty(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } }}二、Redisson工具类
import org.redisson.api.*;import org.redisson.client.codec.StringCodec;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.util.concurrent.TimeUnit;/** * @author: huangyibo * @Date: 2022/6/23 15:01 * @Description: */@Componentpublic class RedisUtils { /** * 默认缓存时间 */ private static final Long DEFAULT_EXPIRED = 32000L; /** * 主动装配redisson client对象 */ @Resource private RedissonClient redissonClient; /** * 用于利用key * @return RKeys 对象 */ public RKeys getKeys() { return redissonClient.getKeys(); } /** * 移除缓存 * * @param key */ public void delete(String key) { redissonClient.getBucket(key).delete(); } /** * 获取getBuckets 对象 * * @return RBuckets 对象 */ public RBuckets getBuckets() { return redissonClient.getBuckets(); } /** * 读取缓存中的字符串,永世有用 * * @param key 缓存key * @return 字符串 */ public String getStr(String key) { RBucket<String> bucket = redissonClient.getBucket(key); return bucket.get(); } /** * 缓存字符串 * * @param key * @param value */ public void setStr(String key, String value) { RBucket<String> bucket = redissonClient.getBucket(key); bucket.set(value); } /** * 缓存带过期时间的字符串 * * @param key 缓存key * @param value 缓存值 * @param expired 缓存过期时间,long范例,必须传值 */ public void setStr(String key, String value, long expired) { RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE); bucket.set(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS); } /** * string 利用,假如不存在则写入缓存(string方式,不带有redisson的格式信息) * * @param key 缓存key * @param value 缓存值 * @param expired 缓存过期时间 */ public Boolean setIfAbsent(String key, String value, long expired) { RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE); return bucket.trySet(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS); } /** * 假如不存在则写入缓存(string方式,不带有redisson的格式信息),永世生存 * * @param key 缓存key * @param value 缓存值 */ public Boolean setIfAbsent(String key, String value) { RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE); return bucket.trySet(value); } /** * 判定缓存是否存在 * * @param key * @return true 存在 */ public Boolean isExists(String key) { return redissonClient.getBucket(key).isExists(); } /** * 获取RList对象 * * @param key RList的key * @return RList对象 */ public <T> RList<T> getList(String key) { return redissonClient.getList(key); } /** * 获取RMapCache对象 * * @param key * @return RMapCache对象 */ public <K, V> RMapCache<K, V> getMap(String key) { return redissonClient.getMapCache(key); } /** * 获取RSET对象 * * @param key * @return RSET对象 */ public <T> RSet<T> getSet(String key) { return redissonClient.getSet(key); } /** * 获取RScoredSortedSet对象 * * @param key * @param <T> * @return RScoredSortedSet对象 */ public <T> RScoredSortedSet<T> getScoredSortedSet(String key) { return redissonClient.getScoredSortedSet(key); }}三、常用RKeys的API利用
每个Redisson对象实例都会有一个与之对应的Redis数据实例,可以通过调用getName方法来取得redis数据实例的名称(key),全部于Redis key相干的利用都归纳在RKeys这个接口里。
RKeys keys = client.getKeys();//获取全部key值Iterable<String> allKeys = keys.getKeys();//含糊查询全部包罗关键字key的值Iterable<String> foundedKeys = keys.getKeysByPattern("key");//删除多个key值long numOfDeletedKeys = keys.delete("obj1", "obj2", "obj3");//含糊删除key值long deletedKeysAmount = keys.deleteByPattern("test?");//随机获取keyString randomKey = keys.randomKey();//查询当前有多少个keylong keysAmount = keys.count();详细demo
private void getKeys() { RKeys keys = redisUtils.getRedisKeys(); Iterable<String> allKeys = keys.getKeys(); StringBuilder sb = new StringBuilder(); for (String key : allKeys) { sb = sb.append(key).append(","); } log.info("全部的key:{}", sb.substring(0, sb.length() - 1)); // 含糊查询以 map 打头的全部 key allKeys = keys.getKeysByPattern("map*"); sb = new StringBuilder(); for (String key : allKeys) { sb = sb.append(key).append(","); } log.info("含糊匹配到的key:{}", sb.substring(0, sb.length() - 1));}此中,getKeysByPattern是基于redis的scan下令实现。
四、通用对象桶Object Bucket
Redisson的分布式RBucket Java对象是一种通用对象桶,可以用来存放恣意范例的对象。除了同步接口外,还提供异步(Async)、反射式(Reactive)和RxJava2尺度的接口。还可以通过RBuckets接口实现批量利用多个RBucket对象。
/** * String 数据范例 */private void strDemo() { redisUtils.setStr(DEMO_STR, "Hello, String."); log.info("String 测试数据:{}", redisUtils.getStr(DEMO_STR)); redisUtils.setStr("myBucket", "myBucketIsXxx"); RBuckets buckets = redisUtils.getBuckets(); Map<String, String> foundBuckets = buckets.get("myBucket*"); Map<String, Object> map = new HashMap<>(); map.put("myBucket1", "value1"); map.put("myBucket2", 30L); // 同时生存全部通用对象桶。 buckets.set(map); Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3"); log.info("跨桶String 测试数据:{}", loadedBuckets); map.put("myBucket3", 320L);}五、散列 Hash
基于Redisson的分布式映射布局的RMap Java对象实现了java.util.concurrent.ConcurrentMap和java.util.Map接口,与HashMap差别的是,RMap 保持了元素的插入次序。该对象的最大容量受Redis限制,最大元素数量是4294967295个。
/** * Hash范例 */private void hashDemo() { RMap<Object, Object> map = redisUtils.getMap("mapDemo"); map.put("demoId1", "123"); map.put("demoId100", "13000"); Object demoId1Obj = map.get("demoId1"); log.info("Hash 测试数据:{}", demoId1Obj);}六、聚集 Set
基于Redisson的分布式Set布局的RSet Java对象实现了java.util.Set接口,通过元素的相互状态比力包管了每个元素的唯一性,该对象的最大容量受Redis限制,最大元素数量是4294967295个。
/** * Set 测试 */private void setDemo() { RSet<String> set = redisUtils.getSet("setKey"); set.add("value777"); log.info("Set 测试数据"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { String next = iterator.next(); log.info(next); }}七、列表 List
基于Redisson的分布式列表 List 布局的RList Java对象在实现了java.util.List接口的同时,确保了元素插入时的次序,该对象的最大容量受Redis限制,最大元素数量是4294967295个。
/** * List数据范例 */private void listDemo() { RList<String> list = redisUtils.getList("listDemo"); list.add("listValue1"); list.add("listValue2"); log.info("List 测试数据:{}", list.get(1));}综合示例
将上述demo放入一个API中,快速测试:
import lombok.extern.slf4j.Slf4j;import org.redisson.api.*;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.HashMap;import java.util.Iterator;import java.util.Map;@Slf4j@RestController@RequestMapping(value = "/redisson", method = RequestMethod.POST)public class StudyRedissonController { @Resource private RedisUtils redisUtils; private static String DEMO_STR = "demoStr"; @PostMapping("/learnRedisson") public void learnRedisson() { //三种数据布局使用示例 strDemo(); hashDemo(); listDemo(); setDemo(); getKeys(); } private void getKeys() { RKeys keys = redisUtils.getKeys(); Iterable<String> allKeys = keys.getKeys(); StringBuilder sb = new StringBuilder(); for (String key : allKeys) { sb = sb.append(key).append(","); } log.info("全部的key:{}", sb.substring(0, sb.length() - 1)); // 含糊查询以 map 打头的全部 key allKeys = keys.getKeysByPattern("map*"); sb = new StringBuilder(); for (String key : allKeys) { sb = sb.append(key).append(","); } log.info("含糊匹配到的key:{}", sb.substring(0, sb.length() - 1)); } /** * Hash范例 */ private void hashDemo() { RMap<Object, Object> map = redisUtils.getMap("mapDemo"); map.put("demoId1", "123"); map.put("demoId100", "13000"); Object demoId1Obj = map.get("demoId1"); log.info("Hash 测试数据:{}", demoId1Obj); } /** * String 数据范例 */ private void strDemo() { redisUtils.setStr(DEMO_STR, "Hello, String."); log.info("String 测试数据:{}", redisUtils.getStr(DEMO_STR)); redisUtils.setStr("myBucket", "myBucketIsXxx"); RBuckets buckets = redisUtils.getBuckets(); Map<String, String> foundBuckets = buckets.get("myBucket*"); Map<String, Object> map = new HashMap<>(); map.put("myBucket1", "value1"); map.put("myBucket2", 30L); // 同时生存全部通用对象桶。 buckets.set(map); Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3"); log.info("跨桶String 测试数据:{}", loadedBuckets); map.put("myBucket3", 320L); } /** * List数据范例 */ private void listDemo() { RList<String> list = redisUtils.getList("listDemo"); list.add("listValue1"); list.add("listValue2"); log.info("List 测试数据:{}", list.get(1)); } /** * Set 测试 */ private void setDemo() { RSet<String> set = redisUtils.getSet("setKey"); set.add("value777"); log.info("Set 测试数据"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { String next = iterator.next(); log.info(next); } }}参考:
https://blog.51cto.com/u_14028890/2308518
https://www.cnblogs.com/east7/p/16255253.html
https://www.cnblogs.com/east7/p/16255305.html |