RedisTemplate
是 Spring Data Redis 提供的一个 Redis 客户端 API,提供了一系列对 Redis 进行 CRUD 操作的方法。以下列举了一部分 RedisTemplate 的操作方法,分别按照 Redis 的数据类型进行分类:
一、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.4.0</version>
</dependency>
二、解決乱码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置Redis连接工厂
template.setConnectionFactory(factory);
// 设置默认的Key序列化器为StringRedisSerializer
template.setDefaultSerializer(new StringRedisSerializer());
// 设置Value序列化器为StringRedisSerializer,并指定字符集编码为UTF-8
template.setValueSerializer(new StringRedisSerializer(Charset.forName("UTF-8")));
return template;
}
}
四、数据类型
1、String(热点缓存、计算器、分布式锁)
方法 | 描述 |
| 获取指定 key 对应的 value |
| 设置指定 key 对应的 value |
| 当指定 key 不存在时,才设置其对应的 value,并返回 true。否则返回 false |
| 给指定 key 对应的 value 增加一个数值 |
| 给指定 key 对应的 value 减去一个数值 |
| 获取旧的 value 并设置新的 value |
| 删除指定的 key 和其对应的 value |
| 同时设置多个 key-value |
| 同时获取多个 key 对应的 value |
1、测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class RedisValueTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void testGet() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 获取指定 key 对应的 value
String value = (String) valueOperations.get("myKey");
System.out.println("Value: " + value);
}
@Test
public void testSet() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 设置指定 key 对应的 value
valueOperations.set("myKey", "myValue");
}
@Test
public void testSetIfAbsent() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 当指定 key 不存在时,才设置其对应的 value,并返回 true;否则返回 false
boolean result = valueOperations.setIfAbsent("myKey", "myValue");
System.out.println("Set if absent result: " + result);
}
@Test
public void testIncrement() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 给指定 key 对应的 value 增加一个数值
Long newNumber = valueOperations.increment("myNumber", 5);
System.out.println("New number: " + newNumber);
}
@Test
public void testDecrement() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 给指定 key 对应的 value 减去一个数值
Long newNumber = valueOperations.decrement("myNumber", 3);
System.out.println("New number: " + newNumber);
}
@Test
public void testGetAndSet() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 获取旧的 value 并设置新的 value
Object oldValue = valueOperations.getAndSet("myKey", "newValue");
System.out.println("Old value: " + oldValue);
}
@Test
public void testDelete() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 删除指定的 key 和其对应的 value
boolean result = valueOperations.getOperations().delete("myKey");
System.out.println("Delete result: " + result);
}
@Test
public void testMultiSet() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 同时设置多个 key-value
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
valueOperations.multiSet(map);
}
@Test
public void testMultiGet() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 同时获取多个 key 对应的 value
List<Object> values = valueOperations.multiGet(Arrays.asList("key1", "key2"));
for (Object value : values) {
System.out.println(value);
}
}
}
2、Hash(存储对象字段、用户属性)
方法 | 描述 |
| 将一个对象以 Hash 方式存储到 Redis 中 |
| 将一个 Map 以 Hash 方式存储到 Redis 中 |
| 获取一个 Hash 中指定的 value |
| 获取一个 Hash 中所有的键值对 |
| 获取一个 Hash 中所有的 key |
| 获取一个 Hash 中所有的 value |
| 删除指定的 Hash 中的一项或多项 |
| 给指定 Hash 中的某个 key 对应的 value 增加一个数值 |
| 判断指定 Hash 中是否存在某个 key |
| 获取指定 Hash 中元素个数 |
2、测试类
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class RedisHashTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String HASH_KEY = "myHash";
@Test
public void testPut() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 将一个对象以 Hash 方式存储到 Redis 中
hashOperations.put(HASH_KEY, "name", "Alice");
hashOperations.put(HASH_KEY, "age", 25);
}
@Test
public void testPutAll() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 将一个 Map 以 Hash 方式存储到 Redis 中
Map<String, Object> map = new HashMap<>();
map.put("name", "Bob");
map.put("age", 30);
hashOperations.putAll(HASH_KEY, map);
}
@Test
public void testGet() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 获取一个 Hash 中指定的 value
String name = (String) hashOperations.get(HASH_KEY, "name");
Integer age = (Integer) hashOperations.get(HASH_KEY, "age");
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
@Test
public void testEntries() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 获取一个 Hash 中所有的键值对
Map<String, Object> entries = hashOperations.entries(HASH_KEY);
for (Map.Entry<String, Object> entry : entries.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
@Test
public void testKeys() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 获取一个 Hash 中所有的 key
List<String> keys = hashOperations.keys(HASH_KEY);
for (String key : keys) {
System.out.println(key);
}
}
@Test
public void testValues() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 获取一个 Hash 中所有的 value
List<Object> values = hashOperations.values(HASH_KEY);
for (Object value : values) {
System.out.println(value);
}
}
@Test
public void testDelete() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 删除指定的 Hash 中的一项或多项
hashOperations.delete(HASH_KEY, "age");
}
@Test
public void testIncrement() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 给指定 Hash 中的某个 key 对应的 value 增加一个数值
Long newAge = hashOperations.increment(HASH_KEY, "age", 5);
System.out.println("New Age: " + newAge);
}
@Test
public void testHasKey() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 判断指定 Hash 中是否存在某个 key
boolean hasKey = hashOperations.hasKey(HASH_KEY, "name");
System.out.println("Has key 'name': " + hasKey);
}
@Test
public void testSize() {
HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
// 获取指定 Hash 中元素个数
Long size = hashOperations.size(HASH_KEY);
System.out.println("Size: " + size);
}
}
3、List(消息队列,获取最新列表等)
方法 | 描述 |
| 向指定 List 的左端(头部)插入一个值 |
| 向指定 List 的左端(头部)插入多个值 |
| 向指定 List 的右端(尾部)插入一个值 |
| 向指定 List 的右端(尾部)插入多个值 |
| 获取指定 List 中指定范围的元素 |
| 获取指定 List 的长度 |
| 保留指定 List 中指定范围内的元素,其余的元素将会被删除 |
| 获取指定 List 中指定索引位置的元素 |
| 移除并返回指定 List 中的第一个元素(左端元素) |
| 移除并返回指定 List 中的最后一个元素(右端元素) |
3、测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.List;
@SpringBootTest
public class RedisListTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void testLeftPush() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 向指定 List 的左端(头部)插入一个值
Long size = valueOperations.leftPush("myList", "value");
System.out.println("List size after left push: " + size);
}
@Test
public void testLeftPushAll() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 向指定 List 的左端(头部)插入多个值
Long size = valueOperations.leftPushAll("myList", "value1", "value2", "value3");
System.out.println("List size after left push all: " + size);
}
@Test
public void testRightPush() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 向指定 List 的右端(尾部)插入一个值
Long size = valueOperations.rightPush("myList", "value");
System.out.println("List size after right push: " + size);
}
@Test
public void testRightPushAll() {
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
// 向指定 List 的右端(尾部)插入多个值
Long size = valueOperations.rightPushAll("myList", "value1", "value2", "value3");
System.out.println("List size after right push all: " + size);
}
@Test
public void testRange() {
List<Object> range = redisTemplate.opsForList().range("myList", 0, -1);
for (Object value : range) {
System.out.println(value);
}
}
@Test
public void testSize() {
Long size = redisTemplate.opsForList().size("myList");
System.out.println("List size: " + size);
}
@Test
public void testTrim() {
redisTemplate.opsForList().trim("myList", 0, 2);
}
@Test
public void testIndex() {
Object value = redisTemplate.opsForList().index("myList", 0);
System.out.println("Value at index 0: " + value);
}
@Test
public void testLeftPop() {
Object value = redisTemplate.opsForList().leftPop("myList");
System.out.println("Left popped value: " + value);
}
@Test
public void testRightPop() {
Object value = redisTemplate.opsForList().rightPop("myList");
System.out.println("Right popped value: " + value);
}
}
4、Set(去重,共同好友、标签系统)
方法 | 描述 |
| 向指定 Set 中添加一个或多个元素 |
| 判断指定 Set 中是否存在指定 value |
| 获取指定 Set 中的所有元素 |
| 移除指定 Set 中一个或多个元素 |
| 获取指定 Set 的元素个数 |
| 获取两个指定 Set 的交集 |
| 获取两个指定 Set 的并集 |
| 获取两个指定 Set 的差集 |
| 移除并返回指定 Set 中的一个随机元素 |
| 随机获取指定 Set 中的多个元素 |
四、测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import java.util.Set;
@SpringBootTest
public class RedisSetTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void testAdd() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 向指定 Set 中添加一个或多个元素
Long count = setOperations.add("mySet", "value1", "value2", "value3");
System.out.println("Number of elements added to the set: " + count);
}
@Test
public void testIsMember() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 判断指定 Set 中是否存在指定 value
Boolean isMember = setOperations.isMember("mySet", "value");
System.out.println("Is 'value' a member of the set? " + isMember);
}
@Test
public void testMembers() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 获取指定 Set 中的所有元素
Set<Object> members = setOperations.members("mySet");
for (Object value : members) {
System.out.println(value);
}
}
@Test
public void testRemove() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 移除指定 Set 中一个或多个元素
Long count = setOperations.remove("mySet", "value1", "value2");
System.out.println("Number of elements removed from the set: " + count);
}
@Test
public void testSize() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 获取指定 Set 的元素个数
Long size = setOperations.size("mySet");
System.out.println("Set size: " + size);
}
@Test
public void testIntersect() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 获取两个指定 Set 的交集
Set<Object> intersect = setOperations.intersect("set1", "set2");
for (Object value : intersect) {
System.out.println(value);
}
}
@Test
public void testUnion() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 获取两个指定 Set 的并集
Set<Object> union = setOperations.union("set1", "set2");
for (Object value : union) {
System.out.println(value);
}
}
@Test
public void testDifference() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 获取两个指定 Set 的差集
Set<Object> difference = setOperations.difference("set1", "set2");
for (Object value : difference) {
System.out.println(value);
}
}
@Test
public void testPop() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 移除并返回指定 Set 中的一个随机元素
Object value = setOperations.pop("mySet");
System.out.println("Popped value: " + value);
}
@Test
public void testRandomMembers() {
SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
// 随机获取指定 Set 中的多个元素
List<Object> randomMembers = setOperations.randomMembers("mySet", 3);
for (Object value : randomMembers) {
System.out.println(value);
}
}
}
Set 是 Redis 中的一种无序集合数据类型,它可以存储多个字符串元素,且每个元素都是唯一的。在 Redis 中,Set 的应用场景非常广泛,下面列举几个常见的应用场景:
1. 标签(Tag)系统
在 Web 应用中,标签系统是一种非常常见的功能。例如,电商网站可以使用标签系统对商品进行分类和搜索,新闻网站可以使用标签系统对文章进行标记和归档。这些标签信息通常都是以 Set 类型进行存储的,每个元素就是一个标签。
2. 集合操作
Set 类型支持多种集合操作,如并集、交集、差集等。这些集合操作可以用于数据统计、推荐算法等场景。例如,一个在线教育平台需要对用户的学科兴趣进行分析,可以使用 Set 存储每个用户的兴趣标签,然后通过集合操作获取不同用户之间的相似度。
3. 订阅与发布
在微信公众号、新浪微博等平台中,用户可以选择关注自己感兴趣的公众号或者博主,并接收他们发布的信息。这种订阅与发布机制可以使用 Set 类型来实现。例如,每个公众号或者博主可以用一个 Set 记录关注他们的用户,当他们发布一条信息时,可以遍历自己的订阅者 Set 并向他们发送信息。
4. 缓存使用
Set 类型也可以用于缓存场景。例如,当需要缓存一个大型数据集合时,可以将这个数据集合转化成多个小集合,并将每个小集合存储在一个 Set 中,然后通过 Set 集合操作来进行数据查询和更新。
总之,Set 类型在 Redis 中被广泛应用于各种场景,包括标签系统、集合操作、订阅与发布机制、缓存等。
5、Sorted Set(排行榜、优先队列等)
方法 | 描述 |
| 向指定的 ZSet 中添加一个元素 |
| 向指定的 ZSet 中批量添加元素 |
| 获取指定 ZSet 中指定范围内的元素(按照 score 从小到大排序) |
| 获取指定 ZSet 中指定范围内的元素(按照 score 从大到小排序) |
| 获取指定 ZSet 中指定范围内的元素及其对应的 score 值 |
| 获取指定 ZSet 中指定范围内的元素及其对应的 score 值(按照 score 从大到小排序) |
| 获取指定 ZSet 中指定元素的排名(按照 score 从小到大排序) |
| 获取指定 ZSet 中指定元素的排名(按照 score 从大到小排序) |
| 获取指定 ZSet 中指定元素对应的 score 值 |
| 获取指定 ZSet 的元素个数 |
5、测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import java.util.Set;
@SpringBootTest
public class RedisZSetTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void testAdd() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 向指定 ZSet 中添加一个元素
Boolean added = zSetOperations.add("myZSet", "value1", 0.5);
System.out.println("Element added to the ZSet: " + added);
}
@Test
public void testAddBatch() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 向指定 ZSet 中批量添加元素
Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
tuples.add(new DefaultTypedTuple<>("value1", 0.5));
tuples.add(new DefaultTypedTuple<>("value2", 0.8));
Long count = zSetOperations.add("myZSet", tuples);
System.out.println("Number of elements added to the ZSet: " + count);
}
@Test
public void testRange() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定范围内的元素(按照 score 从小到大排序)
Set<Object> range = zSetOperations.range("myZSet", 0, -1);
for (Object value : range) {
System.out.println(value);
}
}
@Test
public void testReverseRange() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定范围内的元素(按照 score 从大到小排序)
Set<Object> reverseRange = zSetOperations.reverseRange("myZSet", 0, -1);
for (Object value : reverseRange) {
System.out.println(value);
}
}
@Test
public void testRangeWithScores() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定范围内的元素及其对应的 score 值
Set<ZSetOperations.TypedTuple<Object>> rangeWithScores = zSetOperations.rangeWithScores("myZSet", 0, -1);
for (ZSetOperations.TypedTuple<Object> tuple : rangeWithScores) {
System.out.println("Value: " + tuple.getValue() + ", Score: " + tuple.getScore());
}
}
@Test
public void testReverseRangeWithScores() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定范围内的元素及其对应的 score 值(按照 score 从大到小排序)
Set<ZSetOperations.TypedTuple<Object>> reverseRangeWithScores = zSetOperations.reverseRangeWithScores("myZSet", 0, -1);
for (ZSetOperations.TypedTuple<Object> tuple : reverseRangeWithScores) {
System.out.println("Value: " + tuple.getValue() + ", Score: " + tuple.getScore());
}
}
@Test
public void testRank() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定元素的排名(按照 score 从小到大排序)
Long rank = zSetOperations.rank("myZSet", "value1");
System.out.println("Rank of 'value1' in the ZSet: " + rank);
}
@Test
public void testReverseRank() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定元素的排名(按照 score 从大到小排序)
Long reverseRank = zSetOperations.reverseRank("myZSet", "value1");
System.out.println("Reverse rank of 'value1' in the ZSet: " + reverseRank);
}
@Test
public void testScore() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 中指定元素对应的 score 值
Double score = zSetOperations.score("myZSet", "value1");
System.out.println("Score of 'value1' in the ZSet: " + score);
}
@Test
public void testSize() {
ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
// 获取指定 ZSet 的元素个数
Long size = zSetOperations.size("myZSet");
System.out.println("ZSet size: " + size);
}
}
Sorted Set 由于其可以根据元素分数进行排序,并且每个元素是唯一的,因此在 Redis 中被广泛应用于一些需要按照某个数值排序或者需要去重的场景。下面是具体的一些应用场景:
- 排行榜
在游戏、电商等场景中,需要展示各种排行榜信息,包括积分排行榜、销售额排行榜、热门搜索排行榜等等。对于这些排行榜信息,可以使用 Sorted Set 来存储每个用户或商品的相关信息和相应的分数(如积分、销售额等),然后通过 Sorted Set 的排名功能快速获取排行榜信息。
- 时间轴
在社交网络等场景中,需要展示用户发布的时间轴信息,例如微博动态、朋友圈等等。对于这些时间轴信息,可以使用 Sorted Set 来存储每条动态的发布时间作为分数,然后通过 Sorted Set 的分数范围查询功能快速获取指定时间段内的动态信息。
- 去重
在一些需要去重的业务场景中,可以使用 Sorted Set 来实现数据去重功能。以邮件系统为例,如果需要过滤掉已经处理过的邮件,可以将邮件的 Message-ID 作为 Sorted Set 的成员,将时间戳作为分数,然后查询该邮件 Message-ID 的分数是否存在即可。
- 范围查找
在一些需要进行范围查找的场景中,也可以使用 Sorted Set。例如,有一个地图应用,需要实现搜索附近的 POI(兴趣点)功能,可以将每个 POI 的经纬度作为 Sorted Set 的成员,然后通过 Sorted Set 的分数范围查询功能快速获取指定范围内的 POI 信息。
综上所述,Sorted Set 在 Redis 中被广泛应用于需要按照某个数值排序、去重或者进行范围查找的业务场景。
以上仅是 RedisTemplate 提供的部分方法,其他操作方法请参考 Redis 官方文档或者 Spring Data Redis 的官方文档。