首页 » SEO优化 » phpmapkey技巧_分布式场景Redis客户端最优解决筹划

phpmapkey技巧_分布式场景Redis客户端最优解决筹划

duote123 2024-12-05 0

扫一扫用手机浏览

文章目录 [+]

Copy<参数数量> CRLF$<参数1的字节数量> CRLF<参数1> CRLF...$<参数N的字节数量> CRLF<参数N> CRLF

以set hello world这个命令为例,发送的内容便是这样的:

Copy3SEThelloworld

第一行3表示有3个参数,表示接下来的一个参数有3个字节,接下来是参数,表示下一个参数有5个字节,接下来是参数,表示下一个参数有5个字节,接下来是参数。
以是set hello world终极发送给redis做事器的命令是:

phpmapkey技巧_分布式场景Redis客户端最优解决筹划

Copy3\r\n$3\r\nSET\r\n$5\r\nhello\r\n$5\r\nworld\r\nRESP相应内容

CopyRedis的返回结果类型分为以下五种: 精确回答:在RESP中第一个字节为"+" 缺点回答:在RESP中第一个字节为"-" 整数回答:在RESP中第一个字节为":" 字符串回答:在RESP中第一个字节为"$" 多条字符串回答:在RESP中第一个字节为""

phpmapkey技巧_分布式场景Redis客户端最优解决筹划
(图片来自网络侵删)

(+) 表示一个精确的状态信息,详细信息是当前行+后面的字符。
(-) 表示一个缺点信息,详细信息是当前行-后面的字符。
( ) 表示体统共有多少行,不包括当前行,后面是详细的行数。
(美元符合) 表示下一行数据长度,不包括换行符长度\r\n,$后面则是对应的长度的数据。
(:) 表示返回一个数值,:后面是相应的数字节符。

Java客户端Jedis

传统老牌Java客户端,一贯在更新,对redis命令有比较全面的支持。

优点支持全面的Redis命令,具有全面的API。
缺陷壅塞式I/O,其方法都是同步调用,程序流须要等到 sockets 处理完 I/O 才能实行,不支持异步;Jedis 客户端实例不是线程安全的,以是须要通过连接池来利用 Jedis。
lettuce

lettuce是可扩展的线程安全的客户端,支持异步模式。
如果避免壅塞和事务操作,如BLPOP和MULTI/EXEC,多个线程就可以共享一个连接。
lettuce 底层基于 Netty,支持高等的 Redis 特性,比如哨兵,集群,管道,自动重新连接和Redis数据模型。

优点:支持同步异步通信模式;Lettuce 的 API 是线程安全的,如果不是实行壅塞和事务操作,如BLPOP和MULTI/EXEC,多个线程就可以共享一个连接。
SpringBoot 2.x默认Redis客户端,对Lettuce 供应完美支持Redisson

Redisson 是一个在 Redis 的根本上实现的 Java 驻内存数据网格(In-Memory Data Grid)。
它不仅供应了一系列的分布式的 Java 常用工具,还供应了许多分布式做事。
个中包括( BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson 供应了利用Redis 的最大略和最便捷的方法。
Redisson 的宗旨是促进利用者对Redis的关注分离(Separation of Concern),从而让利用者能够将精力更集中地放在处理业务逻辑上。
优点:

利用者对 Redis 的关注分离,可以类比 Spring 框架,这些框架搭建了运用程序的根本框架和功能,提升开拓效率,让开发者有更多的韶光来关注业务逻辑;供应很多分布式干系操作做事,例如,分布式锁,分布式凑集,可通过Redis支持延迟行列步队等。
缺陷:Redisson 对字符串的操作支持比较差。
Redis Java客户端技能选型

文章基于SpringBoot 2.x进行选型

仅利用Redis进行字符串的数据进行缓存处理,可以利用默认的lettuce。
须要利用Redis做分布式事务,可以选择lettuce + Redisson。
须要缓存分布式凑集数据并对凑集进行频繁读写操作,可以选择lettuce + Redisson。
利用Redis 做行列步队,可以选择lettuce + Redisson。
SpringBoot 集成lettuce + Redisson

在大多数分布式互联网运用中,redis常常用来处理繁芜业务而不是纯挚的字符串存储,比如利用Redis凑集、分布式锁、行列步队等,因此集成lettuce + Redisson,按照不同业务而利用不同组件是比较精良的方案。

集成lettuce引入依赖

<!--spring session--> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>

SpringBoot 2.X默认利用lettuce ,因此供应了比较好的支持,RedisAutoConfiguration完成了对JedisConnectionFactory和LettuceConnectionFactory 的自动配置。
同时RedisProperties封装了redis配置。

添加配置 application.yml

spring: redis: host: 192.168.128.20 #单机配置 port: 6379 #单机配置 #cluster: #nodes: xxxurl 集群配置 # Redis默认情形下有16个分片,配置详细利用的分片,默认为0 database: 0 lettuce: pool: # 连接池最大连接数 默认8 ,负数表示没有限定 max-active: 8 # 连接池最大壅塞等待韶光(利用负值表示没有限定) 默认-1 max-wait: -1 # 连接池中的最大空闲连接 默认8 max-idle: 8 # 连接池中的最小空闲连接 默认0 min-idle: 0集成Redission引入依赖

<!--redisson客户端--> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>${redisson.version}</version> </dependency>添加配置 redisson.yml

redission: pool: # 连接池最大连接数 默认8 ,负数表示没有限定 max-active: 8 # 连接池最大壅塞等待韶光(利用负值表示没有限定) 默认-1 max-wait: -1 # 连接池中的最大空闲连接 默认8 max-idle: 8 # 连接池中的最小空闲连接 默认0 min-idle: 0 connTimeout: 10000 timeout: 3000 soTimeout: 3000 size: 32 #集群配置 cluster: #集群扫描间隔韶光 单位毫秒 scanInterval: 1000 # 只在从做事节点里读取 readMode: "SLAVE" slaveSubscriptionConnectionPoolSize: 50 # 从节点最小空闲连接数 slaveConnectionMinimumIdleSize: 32 # 从节点连接池大小 slaveConnectionPoolSize: 64 # 主节点最小空闲连接数 masterConnectionMinimumIdleSize: 32 # 主节点连接池大小 masterConnectionPoolSize: 64 # 命令失落败重试次数 retryAttempts: 3 # 命令重试发送韶光间隔 retryInterval: 1500 # failedAttempts failedAttempts: 3配置客户端

@EnableConfigurationProperties({RedissionProperties.class, RedisProperties.class})public class RedisConfig { @Value("${spring.profiles.active}") private String env; @Value("${global-conf.active-profiles.prod}") private String activeProd; @Autowired private RedisProperties redisProperties; @Autowired private RedissionProperties redissionProperties; / springboot2.x 利用LettuceConnectionFactory 代替 RedisConnectionFactory 在application.yml配置基本信息后,springboot2.x RedisAutoConfiguration能够自动装置 LettuceConnectionFactory 和 RedisConnectionFactory 及其 RedisTemplate 单机模式和集群模式配置都自动注入,由于在定义Lettuce客户端时无需显示指定模式 @param redisConnectionFactory @return / @Bean public RedisTemplate<String, Object> redisTemplate( LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(redisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(redisSerializer()); return redisTemplate; } @Bean @ConditionalOnProperty(name = "spring.redis.model", havingValue = "single") public RedissonClient getSingleRedisson() { Config config = new Config(); String node = redisProperties.getHost(); //用"rediss://"来启用SSL连接 node = node.startsWith("redis://") ? node : "redis://" + node; SingleServerConfig serverConfig = config.useSingleServer(); serverConfig.setAddress(node) .setConnectionPoolSize(redissionProperties.getPool().getSize()) .setTimeout(redissionProperties.getPool().getTimeout()) .setConnectionMinimumIdleSize(redissionProperties.getPool().getMinIdle()); if (StringUtils.isNotBlank(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } @Bean @ConditionalOnProperty(name = "spring.redis.model", havingValue = "cluster") public RedissonClient getClusterRedisson() { Config config = new Config(); //用"rediss://"来启用SSL连接 List<String> newNodes = redisProperties.getCluster().getNodes() .stream() .map(node -> node.startsWith("redis://") ? node : "redis://" + node) .collect( Collectors.toList()); ClusterServersConfig serverConfig = config.useClusterServers() .addNodeAddress(newNodes.toArray(new String[0])) .setScanInterval( redissionProperties.getCluster().getScanInterval()) .setIdleConnectionTimeout( redissionProperties.getPool().getSoTimeout()) .setConnectTimeout( redissionProperties.getPool().getConnTimeout()) .setRetryAttempts( redissionProperties.getCluster().getRetryAttempts()) .setRetryInterval( redissionProperties.getCluster().getRetryInterval()) .setMasterConnectionPoolSize(redissionProperties.getCluster() .getMasterConnectionPoolSize()) .setSlaveConnectionPoolSize(redissionProperties.getCluster() .getSlaveConnectionPoolSize()) .setTimeout(redissionProperties.getPool().getTimeout()); if (StringUtils.isNotBlank(redisProperties.getPassword())) { serverConfig.setPassword(redisProperties.getPassword()); } return Redisson.create(config); } @Bean public RedisSerializer<Object> redisSerializer() { //创建JSON序列化器 Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>( Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); //必须设置,否则无法将JSON转化为工具,会转化成Map类型 objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(objectMapper); return serializer; } @Bean public RedisCacheManager redisCacheManager(LettuceConnectionFactory redisConnectionFactory) { RedisCacheWriter redisCacheWriter = RedisCacheWriter .nonLockingRedisCacheWriter(redisConnectionFactory); //设置Redis缓存有效期为1天 RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl( Duration.ofDays(1)); return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); }}自定义Redis工具类

常日情形key一样平常是String类型,而value可能不一样,一样平常有两种:String和Object。
如果k-v都是String,我们直策应用StringRedisTemplate

SimpleStringRedisUtil

@Componentpublic class SimpleStringRedisUtil { @Autowired private StringRedisTemplate redisTemplate; / 删除key @param key / public void delete(String key) { redisTemplate.delete(key); } / 序列化key @param key @return / public byte[] dump(String key) { return redisTemplate.dump(key); } / 是否存在key @param key @return / public Boolean exists(String key) { return redisTemplate.hasKey(key); } / 设置指定 key 的值 @param key @param value / public void set(String key, String value) { redisTemplate.opsForValue().set(key, value); } / 写入redis缓存(设置expire存活韶光) @param key @param value @param expire @return / public void set(final String key, String value, Long expire){ ValueOperations operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expire, TimeUnit.SECONDS); } / 获取指定 key 的值 @param key @return / public String get(String key) { return redisTemplate.opsForValue().get(key); }}

如果k-是String,v-是Object,比如Json工具、可序列化工具等,那就须要须要RedisTemplate接口

SimpleObjectRedisUtil

@Componentpublic class SimpleObjectRedisUtil { @Autowired private RedisTemplate redisTemplate; public Set<String> keys(String keys){ try { return redisTemplate.keys(keys); }catch (Exception e){ e.printStackTrace(); return null; } } / 指定缓存失落效韶光 @param key 键 @param time 韶光(秒) @return / public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 指定缓存失落效韶光 @param key 键 @param time 韶光 @param time timeUnit @return / public boolean expire(String key, long time, TimeUnit timeUnit) { try { if (time > 0) { redisTemplate.expire(key, time, timeUnit); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 根据key 获取过期韶光 @param key 键 不能为null @return 韶光(秒) 返回0代表为永久有效 / public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } / 根据key 获取过期韶光 @param key 键 不能为null @param timeUnit @return 韶光(秒) 返回0代表为永久有效 / public long getExpire(String key, TimeUnit timeUnit) { return redisTemplate.getExpire(key, timeUnit); } / 判断key是否存在 @param key 键 @return true 存在 false不存在 / public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } / 删除缓存 @param key 可以传一个值 或多个 / @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } / 普通缓存获取 @param key 键 @return 值 / public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } / 普通缓存放入 @param key 键 @param value 值 @return true成功 false失落败 / public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 普通缓存放入并设置韶光 @param key 键 @param value 值 @param time 韶光(秒) time要大于0 如果time小于即是0 将设置无限期 @return true成功 false 失落败 / public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 普通缓存放入并设置韶光 @param key 键 @param value 值 @param time 韶光 time要大于0 如果time小于即是0 将设置无限期 @param timeUnit @return true成功 false 失落败 / public boolean set(String key, Object value, long time, TimeUnit timeUnit) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, timeUnit); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 递增 @param key 键 @param delta 要增加几(大于0) @return / public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } / 递减 @param key 键 @param delta 要减少几(小于0) @return / public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } / HashGet @param key 键 不能为null @param item 项 不能为null @return 值 / public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } / 获取hashKey对应的所有键值 @param key 键 @return 对应的多个键值 / public Map<Object, Object> hmget(String key) { return redisTemplate.opsForHash().entries(key); } / HashSet @param key 键 @param map 对应多个键值 @return true 成功 false 失落败 / public boolean hmset(String key, Map<String, ?> map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / HashSet 并设置韶光 @param key 键 @param map 对应多个键值 @param time 韶光(秒) @return true成功 false失落败 / public boolean hmset(String key, Map<String, ?> map, long time) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 向一张hash表中放入数据,如果不存在将创建 @param key 键 @param item 项 @param value 值 @return true 成功 false失落败 / public boolean hset(String key, String item, Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 向一张hash表中放入数据,如果不存在将创建 @param key 键 @param item 项 @param value 值 @param time 韶光(秒) 把稳:如果已存在的hash表有韶光,这里将会更换原有的韶光 @return true 成功 false失落败 / public boolean hset(String key, String item, Object value, long time) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 删除hash表中的值 @param key 键 不能为null @param item 项 可以使多个 不能为null / public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } / 判断hash表中是否有该项的值 @param key 键 不能为null @param item 项 不能为null @return true 存在 false不存在 / public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } / hash递增 如果不存在,就会创建一个 并把新增后的值返回 @param key 键 @param item 项 @param by 要增加几(大于0) @return / public double hincr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, by); } / hash递减 @param key 键 @param item 项 @param by 要减少记(小于0) @return / public double hdecr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, -by); } // ===============================Set================================= / 根据key获取Set中的所有值 @param key 键 @return / public Set<Object> sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } / 根据value从一个set中查询,是否存在 @param key 键 @param value 值 @return true 存在 false不存在 / public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } / 将数据放入set缓存 @param key 键 @param values 值 可以是多个 @return 成功个数 / public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } / 将set数据放入缓存 @param key 键 @param time 韶光(秒) @param values 值 可以是多个 @return 成功个数 / public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } / 获取set缓存的长度 @param key 键 @return / public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } / 移除值为value的 @param key 键 @param values 值 可以是多个 @return 移除的个数 / public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } // ===============================list================================= / 获取list缓存的内容 @param key 键 @param start 开始 @param end 结束 0 到 -1代表所有值 @return / public List<Object> lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } / 获取list缓存的长度 @param key 键 @return / public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } / 通过索引 获取list中的值 @param key 键 @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 @return / public Object lGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } / 将list放入缓存 @param key 键 @param value 值 @return / public <T> boolean lSet(String key, T value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 将list放入缓存 @param key 键 @param value 值 @param time 韶光(秒) @return / public <T> boolean lSet(String key, T value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 将list放入缓存 @param key 键 @param value 值 @return / public <T> boolean lSet(String key, List<T> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 将list放入缓存 @param key 键 @param value 值 @param time 韶光(秒) @return / public <T> boolean lSet(String key, List<T> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 根据索引修正list中的某条数据 @param key 键 @param index 索引 @param value 值 @return / public <T> boolean lUpdateIndex(String key, long index, T value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } / 移除N个值为value @param key 键 @param count 移除多少个 @param value 值 @return 移除的个数 / public <T> long lRemove(String key, long count, T value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } /------------------zSet干系操作--------------------------------/ / 添加元素,有序凑集是按照元素的score值由小到大排列 @param key @param value @param score @return / public Boolean zAdd(String key, String value, double score) { return redisTemplate.opsForZSet().add(key, value, score); } / @param key @param values @return / public Long zAdd(String key, Set<ZSetOperations.TypedTuple<String>> values) { return redisTemplate.opsForZSet().add(key, values); } / @param key @param values @return / public Long zRemove(String key, Object... values) { return redisTemplate.opsForZSet().remove(key, values); } / 增加元素的score值,并返回增加后的值 @param key @param value @param delta @return / public Double zIncrementScore(String key, String value, double delta) { return redisTemplate.opsForZSet().incrementScore(key, value, delta); } / 返回元素在凑集的排名,有序凑集是按照元素的score值由小到大排列 @param key @param value @return 0表示第一位 / public Long zRank(String key, Object value) { return redisTemplate.opsForZSet().rank(key, value); } / 返回元素在凑集的排名,按元素的score值由大到小排列 @param key @param value @return / public Long zReverseRank(String key, Object value) { return redisTemplate.opsForZSet().reverseRank(key, value); } / 获取凑集的元素, 从小到大排序 @param key @param start 开始位置 @param end 结束位置, -1查询所有 @return / public Set<String> zRange(String key, long start, long end) { return redisTemplate.opsForZSet().range(key, start, end); } / 获取凑集元素, 并且把score值也获取 @param key @param start @param end @return / public Set<ZSetOperations.TypedTuple<String>> zRangeWithScores(String key, long start, long end) { return redisTemplate.opsForZSet().rangeWithScores(key, start, end); } / 根据Score值查询凑集元素 @param key @param min 最小值 @param max 最大值 @return / public Set<String> zRangeByScore(String key, double min, double max) { return redisTemplate.opsForZSet().rangeByScore(key, min, max); } / 根据Score值查询凑集元素, 从小到大排序 @param key @param min 最小值 @param max 最大值 @return / public Set<ZSetOperations.TypedTuple<String>> zRangeByScoreWithScores(String key, double min, double max) { return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max); } / @param key @param min @param max @param start @param end @return / public Set<ZSetOperations.TypedTuple<String>> zRangeByScoreWithScores(String key, double min, double max, long start, long end) { return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, start, end); } / 获取凑集的元素, 从大到小排序 @param key @param start @param end @return / public Set<String> zReverseRange(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRange(key, start, end); } / 获取凑集的元素, 从大到小排序, 并返回score值 @param key @param start @param end @return / public Set<ZSetOperations.TypedTuple<String>> zReverseRangeWithScores(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end); } / 根据Score值查询凑集元素, 从大到小排序 @param key @param min @param max @return / public Set<String> zReverseRangeByScore(String key, double min, double max) { return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max); } / 根据Score值查询凑集元素, 从大到小排序 @param key @param min @param max @return / public Set<ZSetOperations.TypedTuple<String>> zReverseRangeByScoreWithScores( String key, double min, double max) { return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max); } / @param key @param min @param max @param start @param end @return / public Set<String> zReverseRangeByScore(String key, double min, double max, long start, long end) { return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, start, end); } / 根据score值获取凑集元素数量 @param key @param min @param max @return / public Long zCount(String key, double min, double max) { return redisTemplate.opsForZSet().count(key, min, max); } / 获取凑集大小 @param key @return / public Long zSize(String key) { return redisTemplate.opsForZSet().size(key); } / 获取凑集大小 @param key @return / public Long zZCard(String key) { return redisTemplate.opsForZSet().zCard(key); } / 获取凑集中value元素的score值 @param key @param value @return / public Double zScore(String key, Object value) { return redisTemplate.opsForZSet().score(key, value); } / 移除指定索引位置的成员 @param key @param start @param end @return / public Long zRemoveRange(String key, long start, long end) { return redisTemplate.opsForZSet().removeRange(key, start, end); } / 根据指定的score值的范围来移除成员 @param key @param min @param max @return / public Long zRemoveRangeByScore(String key, double min, double max) { return redisTemplate.opsForZSet().removeRangeByScore(key, min, max); } / 获取key和otherKey的并集并存储在destKey中 @param key @param otherKey @param destKey @return / public Long zUnionAndStore(String key, String otherKey, String destKey) { return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey); } / @param key @param otherKeys @param destKey @return / public Long zUnionAndStore(String key, Collection<String> otherKeys, String destKey) { return redisTemplate.opsForZSet() .unionAndStore(key, otherKeys, destKey); } / 交集 @param key @param otherKey @param destKey @return / public Long zIntersectAndStore(String key, String otherKey, String destKey) { return redisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey); } / 交集 @param key @param otherKeys @param destKey @return / public Long zIntersectAndStore(String key, Collection<String> otherKeys, String destKey) { return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey); } / @param key @param options @return / public Cursor<TypedTuple<String>> zScan(String key, ScanOptions options) { return redisTemplate.opsForZSet().scan(key, options); }}

对付锁、分布式凑集操作、行列步队等分布式工具或做事,利用Redisson。
RedissonClient对锁、凑集、行列步队等分布式操作进行了封装,开拓者只须要大略的调用其接口进行操作:

利用Redisson实现Redis分布式锁 Redisson RLock实现了java.util.concurrent.locks.Lock接口,开拓者可以显示调用Lock接口进行干系锁操作

//根据key获取分布式锁工具-普通可重入锁 RLock lock = redissonClient.getLock("redisKey"); //根据key获取分布式锁工具-公正可重入锁 RLock fairLock = redissonClient.getFairLock("redisKey"); //可重入锁 //不指定时间,当加锁成功后会创建一个锁监听看门狗的监听器, // Redisson实例被关闭前,不断的延长锁的有效期。
// 默认情形下,看门狗的检讨锁的超时时间是30秒钟 //fairLock.lock(); lock.lock(); try { //... } finally { //fairLock.unlock(); lock.unlock(); //须要显示开释锁 } //2. 显示指定加锁韶光 // 加锁往后10秒钟自动解锁 // 无需调用unlock方法手动解锁 //fairLock.lock(10, TimeUnit.SECONDS); lock.lock(10, TimeUnit.SECONDS); try { //... } finally { //fairLock.unlock(); lock.unlock(); //须要显示开释锁 } //3. 考试测验获取锁 // 考试测验加锁,最多等待100秒,上锁往后10秒自动解锁 boolean res = false; try { //res = fairLock.tryLock(100, 10, TimeUnit.SECONDS); res = lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (res) { //fairLock.unlock(); lock.unlock(); //须要显示开释锁 } }
利用Redisson实现凑集操作

@Autowiredprivate RedissonClient redissonClient;//List操作//RList Java工具在实现了java.util.List,同时确保了插入顺序RList nameList = client.getList("redisKey");nameList.clear();nameList.add("bingo");nameList.add("yanglbme");nameList.add("https://github.com/redisson");nameList.remove(-1);boolean contains = nameList.contains("redisson");nameList.forEach(System.out::println); //Hash表//RMap工具实现了`java.util.concurrent.ConcurrentMap`接口和`java.util.Map`接/口。
与HashMap不同的是,RMap保持了元素的插入顺序。
RMap<String, SomeObject> map = redisson.getMap("redisKey");SomeObject prevObject = map.put("redisson1", new SomeObject());SomeObject currentObject = map.putIfAbsent("redisson2", new SomeObject());SomeObject obj = map.remove("redisson1");map.fastPut("redisson1", new SomeObject());map.fastRemove("redisson2");//锁定map内元素RLock keyLock = map.getLock("mapKey");keyLock.lock();try { SomeObjectv = map.get("mapKey"); // 其他业务逻辑} finally { keyLock.unlock();}//读写锁RReadWriteLock rwLock = map.getReadWriteLock("mapKey");rwLock.readLock().lock();try { MyValue v = map.get("mapKey"); // 其他业务逻辑} finally { keyLock.readLock().unlock();}
利用Redission实现延迟行列步队功能

//延迟行列步队工具类@Component@Slf4jpublic class RedisDelayedQueue<T> { @Autowired RedissonClient redissonClient; / 任务回调监听 @param / public abstract static class TaskEventListener<T> { / 实行方法 @param t / public abstract void invoke(T t); } / 添加行列步队 @param t DTO传输类 @param delay 韶光数量 @param timeUnit 韶光单位 / public void addQueue(T t, long delay, TimeUnit timeUnit) { RBlockingQueue blockingFairQueue = redissonClient.getBlockingQueue(t.getClass().getName()); RDelayedQueue delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue); delayedQueue.offer(t, delay, timeUnit); delayedQueue.destroy(); } / 获取行列步队 @param zClass DTO泛型 @param taskEventListener 任务回调监听 @return / public void getQueue(Class zClass, TaskEventListener taskEventListener) { RBlockingQueue blockingFairQueue = redissonClient.getBlockingQueue(zClass.getName()); ((Runnable) () -> { while (true) { try { T t = (T) blockingFairQueue.take(); taskEventListener.invoke(t); } catch (InterruptedException e) { log.error("获取行列步队非常,缘故原由:{}", e); } } }).run(); }}//添加延迟行列步队监听@Component@Slf4jpublic class NotifySubscribeListener implements CommandLineRunner { @Autowired private RedisDelayedQueue redisDelayedQueue; @Autowired private EmsEventQueueHelper emsEventQueueHelper; @Override public void run(String... args) throws Exception { //监听延迟行列步队 RedisDelayedQueue.TaskEventListener taskEventListener = new RedisDelayedQueue.TaskEventListener() { @Override public void invoke(Object o) { EmsEventInfo info = (EmsEventInfo) o; log.info("延迟行列步队实行任务:{}", info.toString()); emsEventQueueHelper.publishEvent(info); } }; redisDelayedQueue.getQueue(EmsEventInfo.class, taskEventListener); }}//行列步队入列//省略...... @Autowired private RedisDelayedQueue redisDelayedQueue;//省略......//入列redisDelayedQueue.addQueue(info, emsTmpProperties.getNotifyTime(), TimeUnit.MINUTES);

标签:

相关文章