RedisTemplate 概述 与 操作 Redis 5 种数据类型
目录
RedisTemplate 概述
Redis 依赖 与 配置
字符串(String) 处理
列表(List) 处理
哈希(Hash) 处理
集合(Set) 处理
有序集合(sorted set)
客户端 Jedis、Redisson、Lettuce 对比
RedisTemplate 概述
1、Redis 是一个缓存、消息代理和功能丰富的键值存储。Spring Boot 为 Lettuce 和 Jedis 客户端库提供基本的自动配置,并为 Spring Data Redis 提供抽象。官网传送。
2、spring-boot-starter-data-redis 启动器,整合了需要的依赖项,默认情况下,它使用 Lettuce 作为客户端。这个启动器同时处理传统应用程序和反应性应用程序(reactive applications)。
3、官方还提供了一个 spring-boot-starter-data-redis-reactive 启动器,用于与具有 reactive 支持的其他存储保持一致。
4、可以像注入任何其他 Spring Bean 一样注入一个自动配置的 RedisConnectionFactory、StringRedisTemplate 或普通的 RedisTemplate 实例。class StringRedisTemplate extends RedisTemplate<String, String>
5、默认情况下,Redis 实例尝试连接本地主机(localhost)端口为 6379 的 Redis 服务器,默认使用空密码,连接 0 号数据库:
REDIS (RedisProperties)
spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.url= # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password@example.com:6379
spring.redis.host=localhost # Redis server host.
spring.redis.jedis.pool.max-active=8 # 池中可以分配的最大连接数,使用负值表示无限制.
spring.redis.jedis.pool.max-idle=8 # 池中'空闲'连接的最大数量,使用负值表示空闲连接的数量不限.
spring.redis.jedis.pool.max-wait=-1ms # 池中连接耗尽时引发异常之前,等待连接分配的最长时间。使用负值可以无限期等待.
spring.redis.jedis.pool.min-idle=0 # 池中要维护的最小空闲连接数的目标,此设置仅在为正时有效.
spring.redis.lettuce.pool.max-active=8 # 池中可以分配的最大连接数,使用负值表示无限制.
spring.redis.lettuce.pool.max-idle=8 #池中'空闲'连接的最大数量,使用负值表示空闲连接的数量不限.
spring.redis.lettuce.pool.max-wait=-1ms # 池中连接耗尽时引发异常之前,等待连接分配的最长时间。使用负值可以无限期等待.
spring.redis.lettuce.pool.min-idle=0 # 池中要维护的最小空闲连接数的目标,此设置仅在为正时有效.
spring.redis.lettuce.shutdown-timeout=100ms # Shutdown timeout.
spring.redis.password= # Login password of the redis server.
spring.redis.port=6379 # Redis server port.
spring.redis.sentinel.master= # Name of the Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of "host:port" pairs.
spring.redis.ssl=false # Whether to enable SSL support.
spring.redis.timeout= # Connection timeout.
6、可以实现 LettuceClientConfigurationBuilderCustomizer 接口,以实现更高级的定制。如果使用的是 Jedis 客户端,则实现 JedisClientConfigurationBuilderCustomizer 接口。
RedisTemplate 默认自己的序列化速度并不理想,实际生产中遇到一次需要将数据库查出来的一个 List 对象放到 Redis 中,当时数据量达到 20 万行,结果 put 的时间长达 6、7 秒,然后当使用 alibaba 的 fastjson 先将 List 对象序列化为字符串,然后在 put 到缓存,此时时间降到了 100 毫秒内,而 fastjson 序列化同样非常之快。取值时,同样将取出的字符串使用 fastjosn 反序列化成 List 即可。 |
Redis 依赖 与 配置
RedisAutoConfiguration 中已经自动将 RedisTemplate 添加到了容器中,直接获取使用即可.
1、RedisTemplate 对 lettuce 与 Jedis 封装之后,使用更加简单,如同使用 JDBCTemplate 对 JDBC 进行了封装。封装之后不需要再关心打开与关闭连接等繁琐的操作,而且它提供性能更好的连接池等。
2、本文环境 Spring Boot 2.1.3 + Java JDK 1.8,pom.xml 文件中导入依赖,然后在需要地方直接注入 RedisTemplate 或者 StringRedisTemplate 使用即可:
<!--Spring Boot redis 启动器-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!--为 redis 导入 commons-pool2 连接池依赖 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.7.0</version>
</dependency>
3、全局配置文件配置 Redis 如下,连接本地没有设置密码的 Redis 服务器:
#Redis 配置,以下除了 timeout 外全部为默认配置.
spring:redis:host: localhostport: 6379database: 0password:timeout: 10000lettuce:pool:max-active: 1000 #池中可以分配的最大连接数,使用负值表示无限制。max-idle: 500 #池中'空闲'连接的最大数量,使用负值表示空闲连接的数量不限。min-idle: 500 #池中要维护的最小空闲连接数的目标,此设置仅在为正时有效。max-wait: -1ms #池中连接耗尽时引发异常之前,等待连接分配的最长时间。使用负值可以无限期等待。
3、Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合),RedisTemplate 分别提供了对应的 API 进行操作它们。
字符串(String) 处理
org.springframework.data.redis.core.ValueOperations 处理 String 类型数据:
方法 | 描述 |
---|---|
set(K key, V value) | 存储到 redis。key 已经存在时,覆盖旧值,不存在时新增。key、value 不能为 null |
set(K key, V value, long timeout, TimeUnit unit) | 设置失效时间为指定时间。超过后 key 会被移除 |
set(K key, V value, Duration timeout) | 设置超时时间,Duration 是 Jdk 8 的 API。超过指定时间后,key 被移除 |
set(K key, V value, long offset) | 覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始 |
get(Object key) | 获取指定 key 的 value,key 不存在时,返回 null。key 不能 null |
getAndSet(K key, V value) | 获取 key 的旧值,并赋值新的 value。key 不能 null |
get(K key, long start, long end) | 获取指定 key 指定范围的字符串 [start,end],从索引 0 开始。key 不能 null |
append(K key, String value) | 将新的 value 追加到 key 的旧值尾部,key 不存在时,自动新建。key 不能为 null。 |
Long size(K key) | 获取 key 的 value 的长度,key 不存在时,返回 0。key 不能为 null。 |
Boolean setIfAbsent(K key, V value) |
如果 key 不存在,则新增,否则不改变原来的值。其余重载方法与 set 方法对应。key、value 不能为 null。 |
Boolean setIfAbsent(K key, V value, long timeout, TimeUnit unit) Boolean setIfAbsent(K key, V value, Duration timeout) |
1、key 不存在时进行设值,返回 true; 否则 key 存在时,不进行设值,返回 false. 2、此方法相当于先设置 key,然后设置 key 的过期时间,它的操作是原子性的,是事务安全的。 3、相当于:SET anyLock unique_value NX PX 30000,NX是指如果key不存在就成功,key存在返回false,PX可以指定过期时间 |
Boolean setIfPresent(K key, V value, Duration timeout) | key 存在时,才修改它的值,否则不新增,与 setIfAbsent 相反。 |
Long increment(K key) | 将存储为字符串值的整数值增加1,并返回结果。key 不存在时自动新增 |
Long increment(K key, long delta) | 将存储为字符串值的整数值增加 delta,并返回结果。key 不存在时自动新增。delta 为负数时,做减法 |
Double increment(K key, double delta) | 将存储为字符串值的小数值增加 delta,并返回结果。key 不存在时自动新增 |
Long decrement(K key) | 将存储为字符串的整数值减1,key 不存在时自动创建 |
Long decrement(K key, long delta) | 减去指定的数值,key 不存在时自动创建。delta |
List multiGet(Collection keys) | 同时获取多个 key 的值,按请求的 key 的顺序返回对应的 value,key 不存在的返回 null。 |
multiSet(Map<? extends K, ? extends V> map) | 同时存储多个 key-value |
Boolean multiSetIfAbsent(Map<? extends K, ? extends V> map) | 当 key 不存在时新增,否则进行操作。 |
ValueOperations源码。
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisStuWebApplicationTests {//注入 RedisTemplate 或者 StringRedisTemplate 其中一个即可,前者是后者的父类,它们都已经默认在 Spring 容器中了。//org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 中已经自动将 RedisTemplate 添加到了容器中,直接获取使用即可.@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate StringRedisTemplate stringRedisTemplate;//org.springframework.data.redis.core.ValueOperations 处理 String 类型数据@Testpublic void test1() {redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();valueOperations.set("user.name", "张无忌 ");//添加值valueOperations.set("upload.process", "65", 60, TimeUnit.SECONDS);//添加值,失效时间60秒valueOperations.set("user.status", "online", Duration.ofSeconds(20));//添加值,失效时间20秒String user_name = valueOperations.get("user.name");//取值String upload_process = valueOperations.get("upload.process");//取值String user_status = valueOperations.get("user.status");//取值String user_status2 = valueOperations.get("user.status", 2, 4);//取值,截取子符串//输出:张无忌 , 65, online, linSystem.out.println(user_name + ", " + upload_process + ", " + user_status + ", " + user_status2);Integer hello = valueOperations.append("user.hit", "Hello");//为末尾追加值String hit1 = valueOperations.get("user.hit");//取值Integer hello2 = valueOperations.append("user.hit", " World");//为末尾追加值String hit2 = valueOperations.get("user.hit");//取值Long size = valueOperations.size("user.hit");//字符串的长度//输出:5 - Hello, 11 - Hello WorldSystem.out.println(hello + " - " + hit1 + ", " + hello2 + " - " + hit2 + ", " + size);//key 不存在时,才进行添加Boolean aBoolean1 = valueOperations.setIfAbsent("name", "三丰", 60, TimeUnit.SECONDS);Boolean aBoolean2 = valueOperations.setIfAbsent("name", "四喜", 60, TimeUnit.SECONDS);System.out.println(aBoolean1 + ", " + aBoolean2 + ", " + valueOperations.get("name"));//输出:true, false, 三丰//key 存在时,才进行添加Boolean age1 = valueOperations.setIfPresent("age", "45", Duration.ofSeconds(60));valueOperations.set("age", "35");Boolean age2 = valueOperations.setIfPresent("age", "55", Duration.ofSeconds(60));System.out.println(age1 + ", " + age2 + ", " + valueOperations.get("age"));//输出:false, true, 55valueOperations.set("l1", "1", Duration.ofSeconds(60));valueOperations.set("d1", "3.14", Duration.ofSeconds(60));valueOperations.set("total", "100", Duration.ofSeconds(60));Long count1 = valueOperations.increment("l1");//数值做加法Long count2 = valueOperations.increment("l1", 10L);Double d1 = valueOperations.increment("d1", 40.00);Long total1 = valueOperations.decrement("total");//数值做减法Long total2 = valueOperations.decrement("total2", 35);System.out.println(count1 + ", " + count2 + ", " + d1 + ", " + total1 + ", " + total2);//输出:2, 12, 43.14, 99, 64List<String> keyList = new ArrayList<>();keyList.add("l1");keyList.add("d1");keyList.add("f1");List<String> list = valueOperations.multiGet(keyList);//同时获取多个 key 的 valueSystem.out.println(list);//[12, 43.140000000000001, null]Map<String, String> dataMap = new LinkedHashMap<>();dataMap.put("multi_name", "雄霸");dataMap.put("multi_age", "44");valueOperations.multiSet(dataMap);//同时设置多个key-value//输出:[雄霸, 44]System.out.println(valueOperations.multiGet(Arrays.asList(new String[]{"multi_name", "multi_age"})));}
}
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
列表(List) 处理
org.springframework.data.redis.core.ListOperations 处理 List 类型数据:
方法 | 描述 |
---|---|
Long size(K key) | 返回存储在键中的列表的长度。键不存在时,返回 0;key 存储的值不是列表时返回错误。 |
Long leftPush(K key, V value | 将指定的值插入到列表的头部。键不存在自动创建。(从左边插入)。返回 list 的大小(size)。 |
Long leftPushAll(K key, V... values) | 批量从左插入。key 不能为 null。返回 list 的大小(size)。 |
Long leftPushAll(K key, Collection values) | 批量从左插入。key,values 不能为 null。 |
Long leftPush(K key, V pivot, V value) | 对于名字为 key 的 list,从左往右先查询第一个出现的 pivot 元素,然后将 value 插入到它的左边。 |
Long leftPushIfPresent(K key, V value) | 只有当 key 存在时,才新增,否则不处理。 |
Long rightPush(K key, V value) | 右侧插入,key 不存在时,自动创建 |
Long rightPush(K key, V pivot, V value) | 从左往右查找第一个 pivot 元素,然后将新的 value 插入到它的右侧。 |
Long rightPushAll(K key, Collection values) | 右侧批量插入 |
Long rightPushAll(K key, V... values) | 右侧批量插入 |
Long rightPushIfPresent(K key, V value) | 当 key 存在时,进行右侧插入,否则不处理。 |
set(K key, long index, V value) | 为名字为 key 的列表索引为 index 的元素替换为新的 value 值。key 必须存在,index 索引不能越界 |
Long remove(K key, long count, Object value) | 删除列表(key) 中指定个数(count)的元素(value)。count=0:删除所有 value;count>0:从左往右删除 count 个 value;count<0,从右往左删除。 |
List range(K key, long start, long end) | 查询 list 的元素值,索引范围为 [start,end],-1 表示倒数第一个元素 |
V index(K key, long index) | 获取列表中指定索引处的元素。index 越界时,返回 null;key 不存在时,返回 null。索引 index=-1 表示倒数第一个元素。 |
V leftPop(K key) | 弹出最左边的元素,弹出之后该值在列表中将不复存在。当列表为空时,返回 null。 |
V rightPop(K key) | 弹出最右边的元素,弹出之后该值在列表中将不复存在。当列表为空时,返回 null。 |
V leftPop(K key, long timeout, TimeUnit unit) | 弹出最左边的元素,当元素不存在时,线程阻塞等待,直到存在新元素,或者超时抛出异常 |
V rightPop(K key, long timeout, TimeUnit unit) | 弹出最右边的元素,当元素不存在时,线程阻塞等待,直到存在新元素,或者超时抛出异常 |
ListOperations 源码。
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
//org.springframework.data.redis.core.ListOperations 处理 List 类型数据@Testpublic void test2() {redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。ListOperations<String, String> opsForList = stringRedisTemplate.opsForList();Long aLong1 = opsForList.leftPush("list_1", "USA");//将值添加到 list 头部Long aLong2 = opsForList.leftPush("list_1", "China");//将值添加到 list 头部Long aLong3 = opsForList.leftPushAll("list_1", new String[]{"Java", "C++", "USA", "WPF"});//将多个值添加到 list 头部Long size = opsForList.size("list_1");//获取 list 大小Long aLong4 = opsForList.leftPush("list_1", "Java", "C#");//将值添加到 list 头部Long aLong5 = opsForList.rightPush("list_1", "USA", "Tomcat");//将值添加到 list 头部//输出:1, 2, 6, 7, 8, 6System.out.println(aLong1 + ", " + aLong2 + ", " + aLong3 + ", " + aLong4 + ", " + aLong5 + ", " + size);System.out.println(opsForList.range("list_1", 0, -1));//输出:[WPF, USA, Tomcat, C++, C#, Java, China, USA]Long aLong = opsForList.leftPushIfPresent("list_2", "Apple");//当 key 存在时,才进行添加System.out.println(aLong + ", " + aLong5);//0, 8opsForList.rightPush("list_2", "2019");//将值添加到 list 尾部opsForList.rightPush("list_2", "2018");opsForList.rightPush("list_2", "2017");opsForList.set("list_2", 1, "2008");System.out.println(opsForList.range("list_2", 0, -1));//获取指定索引范围的值,[2019, 2008, 2017]//同时将多个值添加到右侧opsForList.rightPushAll("list_3", new String[]{"mysql", "oracle", "sql server", "redis", "oracle", "sql server", "redis", "oracle"});System.out.println(opsForList.range("list_3", 0, -1));//输出:[mysql, oracle, sql server, redis, oracle, sql server, redis, oracle]//删除 list 中所有的 "sql server" 值Long remove1 = opsForList.remove("list_3", 0, "sql server");//2 - [mysql, oracle, redis, oracle, redis, oracle]System.out.println(remove1 + " - " + opsForList.range("list_3", 0, -1));//从右往左删除第一次出现的 redis 值Long remove2 = opsForList.remove("list_3", -1, "redis");//1 - [mysql, oracle, redis, oracle, oracle]System.out.println(remove2 + " - " + opsForList.range("list_3", 0, -1));//从左往右删除第一次、第二次出现的 oracle 值Long remove3 = opsForList.remove("list_3", 2, "oracle");//2 - [mysql, redis, oracle]System.out.println(remove3 + " - " + opsForList.range("list_3", 0, -1));opsForList.rightPushAll("list_4", new String[]{"mysql", "oracle", "redis", "DB2"});String index1 = opsForList.index("list_4", -1);//查询倒数第一个元素String leftPop1 = opsForList.leftPop("list_4");//弹出头部第一个元素String rightPop1 = opsForList.rightPop("list_4");//弹出尾部第一个元素System.out.println(index1 + ", " + leftPop1 + ", " + rightPop1);//DB2, mysql, DB2opsForList.rightPushAll("list_5", new String[]{"Python", "C#", "Java"});for (int i = 0; i < 4; i++) {//弹出头部元素,当超过60秒还没有元素时,抛出异常 RedisCommandTimeoutException//System.out.println(opsForList.leftPop("list_5", 60, TimeUnit.SECONDS));//可以手动通过 redis 客户添加元素:lpush list_5 wmx}}
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
哈希(Hash) 处理
org.springframework.data.redis.core.HashOperations 处理 Hash 类型数据:
方法 | 描述 |
---|---|
Long size(H key) | 获取指定 hash(key) 的元素个数,kye 不存在时,返回 0 |
Boolean hasKey(H key, Object hashKey) | 判断 hash 中 是否存在指定的元素,key 不存在时,返回 false |
Set keys(H key) | 获取指定 hash(key) 中所有的 hashKey。key 不存在时,返回空集合[]. |
List values(H key) | 获取指定 hash(key) 的所有值。key 不存在时,返回空 list |
Long delete(H key, Object... hashKeys) | 删除指定的 hash(key) 中指定的元素(hansKeys),返回成功删除元素个数,key 不存在时返回 0 |
void put(H key, HK hashKey, HV value) | 往 key 中插入键值对 hashKey-value。hashKey 重复时,后插入的覆盖旧值。key 不存在时,自动新增 |
void putAll(H key, Map<? extends HK, ? extends HV> m) | 单次插入多个元素。key 不存在时自动新增 |
Boolean putIfAbsent(H key, HK hashKey, HV value) | key 或者 hashKey 不存在时,才插入值 |
HV get(H key, Object hashKey) | 获取 hash 中指定的 hashKey,key 不存在时,返回 null. |
Map<HK, HV> entries(H key) | 获取指定 key 的 hash map。key 不存在时,返回空 map。 |
Long lengthOfValue(H key, HK hashKey) | 获取 key 对应的 hash map 的 hashKey 对应的元素值的长度 |
List multiGet(H key, Collection hashKeys) | 同时获取 key 对应的 hash map 中的多个元素值,hashKey 不存在时,返回 null |
Long increment(H key, HK hashKey, long delta) | 为指定 key 的 hash map 中的元素 hashKey 的数值加上整数值 delta。key 不存在时,直接新增。 |
Double increment(H key, HK hashKey, double delta) | 为指定 key 的 hash map 中的元素 hashKey 的数值加上浮点数值 delta。key 不存在时,直接新增 |
HashOperations 源码。
//org.springframework.data.redis.core.HashOperations 处理 hash 数据类型@Testpublic void test3() {redisTemplate.getConnectionFactory().getConnection().flushAll();//清空 redis 所有缓存的数据。HashOperations<String, Object, Object> opsForHash = stringRedisTemplate.opsForHash();Long delete = opsForHash.delete("hash_1", "name", "age");//删除指定元素Boolean hasKey = opsForHash.hasKey("hash_1", "name");//判断是否含有指定的元素Object name1 = opsForHash.get("hash_1", "name");//获取指定的元素Set<Object> keys = opsForHash.keys("hash_1");//获取所有的 keyLong hash_1 = opsForHash.size("hash_1");//获取 hash 的大小System.out.println(delete + ", " + hasKey + ", " + name1 + ", " + keys + ", " + hash_1);//输出:0, false, null, [], 0Map<String, String> dataMap = new HashMap<>();dataMap.put("age", "33");dataMap.put("name", "Li Si");dataMap.put("address", "人民东路45号");opsForHash.put("hash_1", "name", "Zan San");//为 hash 添加单个元素opsForHash.putAll("hash_1", dataMap);//为 hash 添加多个元素opsForHash.putIfAbsent("hash_2", "name", "Chang Sha");//当 key 或者 hashKey 不存在时,才插入值List<Object> list = opsForHash.values("hash_1");//获取所有的 valuesMap<Object, Object> entries = opsForHash.entries("hash_1");//获取整个 hashLong lengthOfValue1 = opsForHash.lengthOfValue("hash_1", "name");//获取元素的长度Long lengthOfValue2 = opsForHash.lengthOfValue("hash_1", "age");List<Object> multiGet = opsForHash.multiGet("hash_1", Arrays.asList(new String[]{"name", "address", "birthday"}));//同时获取多个元素值//[Li Si, 人民东路45号, 33], {name=Li Si, address=人民东路45号, age=33}, 5, 2, [Li Si, 人民东路45号, null]System.out.println(list + ", " + entries + ", " + lengthOfValue1 + ", " + lengthOfValue2 + ", " + multiGet);Long increment_age1 = opsForHash.increment("hash_1", "age", 20);//数值元素做加法Double increment_age2 = opsForHash.increment("hash_1", "age", 20.45D);System.out.println(increment_age1 + ", " + increment_age2);//53, 73.45}
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
集合(Set) 处理
org.springframework.data.redis.core.SetOperations 处理无序集合(Set) 类型数据:
方法 | 描述 |
---|---|
Long add(K key, V... values) | 往 set 中添加元素,key 不存在时,自动新建。value 重复时,覆盖旧值。返回 set 中的元素个数 |
Long remove(K key, Object... values) | 移除 set 中的元素。返回 set 中剩余的元素个数. |
Boolean move(K key, V value, K destKey) | 将 key 对应的 set 中的值 value 剪切到目标 set(destKey) 中。key、value、destKey 不存在时,不做任何操作. |
V pop(K key) | 随机弹出 set 中的一个元素,弹出后,set 中就没有了。当 set 为空时,返回 null. |
List pop(K key, long count) | 随机弹出 set 中 count 个元素,如果 set 的大小为 3,而 count 为 5,此时只会返回 3 个元素。 |
Long size(K key) | 获取 key 对应 set 的集合大小. key 不存在时,返回 0 |
Set members(K key) | 获取 set 中所有的元素,key 不存在时,返回空 set. |
V randomMember(K key) | 从 set 中随机返回一个元素,set 中此元素还会存在。key 不存在时,返回 null. |
List randomMembers(K key, long count) | 随机返回 set 中 count 个元素。 |
Boolean isMember(K key, Object o) | 判断 key 对应的 set 中是否包含元素 o。key 不存在时,返回 false。 |
Set union(K key, K otherKey) | 获取 key 与 otherKey 对应的 set 的并集。旧值不受影响,返回合并后的值。 |
Set union(K key, Collection otherKeys) | 获取多个 set 的并集 |
Long unionAndStore(K key, K otherKey, K destKey) | 求 key 、otherKey 的 set 并集,并将结果添加到 destKey 中。destKey 不存在时,自动创建。返回新集合中的元素个数。当 destKey 中事先已经有值,则会被先清除。 |
Long unionAndStore(K key, Collection otherKeys, K destKey) | 将多个 set 的并集结果放入到 destKey 对应的 set 中,destKey 不存在时,自动创建。当 destKey 中事先已经有值,则会被先清除。 |
Set difference(K key, K otherKey) | 求 key 与 otherKey 对应的 set 的差集,key 减去 otherKey 后剩余的结果。 |
Set difference(K key, Collection otherKeys) | 获取 key 与所有 otherKeys 的差集。 |
Long differenceAndStore(K key, K otherKey, K destKey) | 将差集结果放入到 destKey 中。当 destKey 中事先已经有值,则会被先清除。 |
Long differenceAndStore(K key, Collection otherKeys, K destKey) | 将差集结果放入到 destKey 中。当 destKey 中事先已经有值,则会被先清除。 |
Set intersect(K key, K otherKey) | 获取 key 与 otherKey 的交集,双方都拥有的元素 |
Set intersect(K key, Collection otherKeys) | 获取 key 与其它所有 otherKeys 的交集 |
Long intersectAndStore(K key, K otherKey, K destKey) | 将交集结果放到 destKey 集合中。当 destKey 中事先已经有值,则会被先清除。 |
Long intersectAndStore(K key, Collection otherKeys, K destKey) | 将交集结果放到 destKey 集合中。当 destKey 中事先已经有值,则会被先清除。 |
SetOperations 源码。
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
//org.springframework.data.redis.core.SetOperations 处理 Set 类型数据:@Testpublic void test4() {stringRedisTemplate.getConnectionFactory().getConnection().flushAll();//情况所有缓存数据SetOperations<String, String> opsForSet = stringRedisTemplate.opsForSet();Long add = opsForSet.add("set_1", "C", "Java", "Python");//往集合添加元素Long remove = opsForSet.remove("set_1", "C");//删除元素String set_1 = opsForSet.pop("set_1");//随机弹出 set 中的一个元素System.out.println(add + ", " + remove + ", " + set_1);//3, 1, PythonopsForSet.add("set_2", "华山", "泰山", "衡山");Set<String> set_2 = opsForSet.members("set_2");//查询 set 中的所有元素opsForSet.move("set_1", "Java", "set_2");System.out.println(set_2);//[泰山, 衡山, 华山]Long size = opsForSet.size("set_2");//获取 set 的大小System.out.println(opsForSet.members("set_2") + ", " + size);//[泰山, 衡山, 华山], 3Boolean member1 = opsForSet.isMember("set_2", "泰山");//判断 set 中是否含义指定的元素值Boolean member2 = opsForSet.isMember("set_2", "嵩山");System.out.println(member1 + ", " + member2);//true, falseopsForSet.add("set_3", "Oracle", "Mysql", "DB2", "H2", "Sql Server");List<String> set_3 = opsForSet.pop("set_3", 3);System.out.println(set_3);//[Oracle, DB2, Mysql]opsForSet.add("set_4", "段誉", "乔峰", "虚竹", "王语嫣", "慕容复");System.out.println(opsForSet.members("set_4") + ", " + opsForSet.randomMember("set_41"));System.out.println(opsForSet.randomMembers("set_4", 3));//随机弹出 set 中指定个数的元素,如随机弹出其中3个元素opsForSet.add("set_5_1", "a", "b", "c", "1", "2", "3");opsForSet.add("set_5_2", "x", "y", "c", "21", "2", "3");Set<String> union1 = opsForSet.union("set_5_1", "set_5_2");//两个集合求并集System.out.println(opsForSet.members("set_5_1") + ", " + opsForSet.members("set_5_2"));System.out.println(union1);//[3, a, x, c, b, 2, 21, 1, y]//多个集合求并集Set<String> set_5_1 = opsForSet.union("set_5_1", Arrays.asList(new String[]{"set_5_2", "set_4"}));System.out.println(set_5_1);//[王语嫣, 段誉, 21, a, 3, 虚竹, x, b, c, 慕容复, 1, y, 乔峰, 2]//多个集合求并集,并将结果存储到新的集合中Long aLong = opsForSet.unionAndStore("set_5_1", "set_5_2", "set_5_3");System.out.println(aLong + ", " + opsForSet.members("set_5_3"));//9, [3, a, x, c, b, 2, 21, 1, y]Set<String> difference = opsForSet.difference("set_5_1", "set_5_2");//求两个集合的差集System.out.println(difference);//[a, 1, b]Set<String> intersect = opsForSet.intersect("set_5_1", "set_5_2");//求两个集合的交集opsForSet.intersectAndStore("set_5_1", "set_5_2", "set_5_3");//当set_5_3集合中有值时,会先被清除System.out.println(intersect);//[3, c, 2]}
有序集合(sorted set)
org.springframework.data.redis.core.ZSetOperations 处理有序集合(Set) 的数据:
方法 | 描述 |
---|---|
Boolean add(K key, V value, double score) | 为有序集合添加元素. 如果 value 已经存在,则更新. score 表示权重,用于排序,值越小,排序越靠前(由小到大)。key 不存在时,直接新增。成功插入时返回 true,失败时返回 false。 |
Long rank(K key, Object o) | 获取元素 o 在有序集合中的索引 |
Set range(K key, long start, long end) | 获取有序的集合中指定索引范围的值,索引从0开始,-1 表示倒数第一个元素。 |
Set rangeByScore(K key, double min, double max) | 根据权重范围查询 |
Set rangeByScore(K key, double min, double max, long offset, long count) | offset 表示偏移量,count 表示需要获取的个数 |
Long count(K key, double min, double max) | 获取权重在 [min,max] 直接的元素个数 |
Long remove(K key, Object... values) | 删除有序集合中指定的元素(value) |
Long removeRange(K key, long start, long end) | 删除有序集合中指定索引范围内的元素 |
Long removeRangeByScore(K key, double min, double max) | 删除有序集合中指定权重范围内的元素 |
Long zCard(K key) | 获取集合的大小 |
Long size(K key) | 获取集合的大小,底层调用 zCard |
Double score(K key, Object o) | 获取集合中指定元素的权重。 |
ZSetOperations 源码。
本文演示源码:src/test/java/com/wmx/wmxredis/RedisTest.java · 汪少棠/wmx-redis - Gitee.com
//org.springframework.data.redis.core.ZSetOperations 处理有序集合(Set) 的数据:@Testpublic void test5() {stringRedisTemplate.getConnectionFactory().getConnection().flushAll();//清空所有缓存ZSetOperations<String, String> opsForZSet = stringRedisTemplate.opsForZSet();Boolean add1 = opsForZSet.add("zset1", "C++", 3.8);Boolean add2 = opsForZSet.add("zset1", "Java", 0.3);Boolean add3 = opsForZSet.add("zset1", "Python", 2.5);Set<String> zset1 = opsForZSet.range("zset1", 0, -1);System.out.println(add1 + ", " + add2 + ", " + add3 + ", " + zset1);//输出:true, true, true, [Java, Python, C++]Long rank = opsForZSet.rank("zset1", "C++");Long count = opsForZSet.count("zset1", 0.3, 2.5);Long size = opsForZSet.size("zset1");Double score = opsForZSet.score("zset1", "Java");//输出:2, 2, 3, 0.3, [Java, Python, C++]System.out.println(rank + ", " + count + ", " + size + ", " + score + ", " +opsForZSet.range("zset1", 0, -1));opsForZSet.add("zset2", "12", 0);opsForZSet.add("zset2", "3c", 1);opsForZSet.add("zset2", "4f", 2);opsForZSet.add("zset2", "6h", 3);opsForZSet.add("zset2", "7p", 4);Long remove = opsForZSet.remove("zset2", "4f");//Long aLong = opsForZSet.removeRange("zset2", 1, 2);Long zset2 = opsForZSet.removeRangeByScore("zset2", 2.0, 3.0);System.out.println(opsForZSet.range("zset2", 0, -1));}
客户端 Jedis、Redisson、Lettuce 对比
1、三个都提供了基于 Redis 操作的 Java API,只是封装程度,具体实现稍有不同。
Jedis |
Java 实现的客户端。支持基本的数据类型如:String、Hash、List、Set、Sorted Set。 使用阻塞的 I/O,方法调用同步,程序流需要等到 socket 处理完 I/O 才能执行,不支持异步操作。Jedis 客户端实例不是线程安全的,需要通过连接池来使用 Jedis。 |
Redisson | 分布式锁,分布式集合,可通过 Redis 支持延迟队列。 |
Lettuce |
用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。 基于 Netty 框架的事件驱动的通信层,其方法调用是异步的。Lettuce 的 API 是线程安全的,所以可以操作单个 Lettuce 连接来完成各种操作。 |
RedisTemplate 概述 与 操作 Redis 5 种数据类型相关推荐
- redis五种数据类型及其常见操作
redis五种数据类型及其常见操作 Redis支持5种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 1.strin ...
- Redis八种数据类型及应用场景介绍
本文来说下Redis八种数据类型及应用场景介绍 文章目录 概述 String 介绍 应用场景 Hash 介绍 应用场景 List 介绍 应用场景 Set 介绍 应用场景 ZSet 介绍 应用场景 Bi ...
- Redis五种数据类型介绍
概述 Redis的键值可以使用物种数据类型:字符串,散列表,列表,集合,有序集合.本文详细介绍这五种数据类型的使用方法.本文命令介绍部分只是列举了基本的命令,至于具体的使用示例,可以参考Redis官方 ...
- Redis五种数据类型及应用场景
Redis五种数据类型及应用场景 MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样 ...
- redis五种数据类型的使用场景
string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...
- 2 万字 + 20张图| 细说 Redis 九种数据类型和应用场景
作者:小林coding 计算机八股文网(操作系统.计算机网络.计算机组成.MySQL.Redis):https://xiaolincoding.com 大家好,我是小林. 我们都知道 Redis 提供 ...
- Redis五种数据类型
Redis五种数据类型:字符串 String,哈希 hash,列表 list ,集合 set,有序集合 softed set String(字符串) • 二进制安全,可存储任何数据,如图片或者序列化对 ...
- Redis五种数据类型及命令(一)
Redis 五种数据类型详解及命令 Redis五种数据类型分别为: String:最基本的字符串类型. list:列表(如果对比java来看,这个list不是ArrayList,而是LinkedLis ...
- redis五种数据类型对应的底层数据结构
redis五种数据类型对应的底层数据结构 redis的五种数据类型 redis核心对象redisObject type数据类型 encoding编码类型 ptr指针 redis五种数据类型对应的底层数 ...
- redis缓存路由为空_Springboot使用RedisTemplate优雅地操作redis
作者:Jantihttp://cnblogs.com/superfj/p/9232482.html 概述 本文内容主要 关于spring-redis 关于redis的key设计 redis的基本数据结 ...
最新文章
- iOS开展block说明
- Hadoop-2.2.0学习之二HDFS联盟
- android中判断设备定位状态
- 2022年全球及中国建筑隔震系统行业设施布局与十四五应用决策建议报告
- wxWidgets:添加菜单栏
- 【PAT - 甲级1004】Counting Leaves (30分) (dfs,递归)
- 华为机试——进制转换
- Layui 获取表单提交数据
- 关于WordPress登录后跳转到指定页面
- 固定资产分类(仅供参考 2005年),
- Python算法教程:强连通分量
- 【梦幻西游】12门派版一键端
- Google的快照的用户体验感觉不如之前
- java上传下载原理_Java上传下载文件原理
- 分辨率、像素、像素尺寸、GSD、图片文件大小
- 好用的excel图片转表格的方法都在这了
- 设备功耗计算专题《低功耗实战篇,全志XR808连接AP的最低功耗研究》
- ehvierwer登录与不登录_微信上不去了怎么办,峰哥教你微信登录不上去的办法
- 柠檬班的课程怎么样,来自一个金融行业转行到软件测试行业的故事
- 转载蓝叠模拟器与android studio连接步骤
热门文章
- 如何将MyEclipse开发的项目导入到Eclipse中运行
- 第十天学习@javascript
- 孙鑫VC学习笔记:第十一讲 (二) 图形的保存与重绘方法一
- php中怎样阻止网页进行跳转,PHP中阻止网页进行跳转的方法
- 上海自考计算机及应用,上海交通大学--计算机及应用(独立本科080901)
- katakana.php,片假名 平假名转换器 - Hi!Penpal!
- 拓端tecdat|WinBUGS对多元随机波动率模型:贝叶斯估计与模型比较
- 7-21 九宫格输入法 (15 point(s))
- 检查pandas是否存在一列或者多列
- Caffe学习2:Blob