广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >浅谈RedisTemplate和StringRedisTemplate的区别
  • 185
分享到

浅谈RedisTemplate和StringRedisTemplate的区别

2024-04-02 19:04:59 185人浏览 泡泡鱼
摘要

目录一、区别二、问题总结三、案例:SpringBoot整合Redis五种数据结构api1、string(字符串)类型2、hash(哈希)类型3、list(列表)类型4、set(无序集

一、区别

  • 区别点1:两者的关系是StringRedisTemplate继承RedisTemplate。RedisTemplate是一个泛型类,而StringRedisTemplate则不是。
  • 区别点2:两者序列化策略不同,
  • StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
  • RedisTemplate默认采用的是jdk的序列化策略,保存的key和value都是采用此策略序列化保存的。
  • 区别点3:(疑惑点)两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
  • 区别点4:StringRedisTemplate只能对key=String,value=String的键值对进行操作,RedisTemplate可以对任何类型的key-value键值对操作。

二、问题总结

问题1:究竟是数据隔离?还是存入的数据访问不到?用词是否严谨?

答案:严谨说并不是数据隔离,而应该说成是彼此存入redis的数据存在,但是访问不到;而数据隔离通常指的是数据存在同一个库下,但是自己只能查看并访问自己的数据,而redis中数据都能看到且只是使用不同RedisTemplate和StringRedisTemplate对象彼此访问不到而已。

问题2:(重要)我自己测试RedisTemplate和StringRedisTemplate居然都可以彼此访问到存取的字符串值,为啥?别人文章说数据不共通

答案:所谓的彼此访问不到数据,前提是自己不重新对RedisTemplate进行序列化设置,大白话讲就是直接使用默认的,这样才能实现彼此数据隔离访问不到,而实现了序列化后RedisTemplate和StringRedisTemplate对字符串类型数据就都能获取了。

而我的能访问到就是我对RedisTemplate进行了序列化设置,比如如下代码,注意这一行: template.seTKEySerializer(RedisSerializer.string());这样设置后就会导致RedisTemplate和StringRedisTemplate针对string类型的属性值使用了相同的序列化方式,这样就能彼此访问到数据了;反之不设置这一行,就会彼此反问不到数据。

package com.example.demo.config;

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.GenericJackson2JSONRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig  {
   
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //key的序列化采用String类型的
        template.setKeySerializer(RedisSerializer.string());
        //value的序列化采用jackson类型
        template.setValueSerializer(new GenericJackson2jsonRedisSerializer());
        //hash的key的序列化也采用String类型
        template.setHashKeySerializer(RedisSerializer.string());
        //value的序列化采用jackson类型
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

问题3:.源码分析RedisTemplate和StringRedisTemplate的序列化方式

RedisTemplate的序列化

StringRedisTemplate的序列化

问题4:.RedisTemplate和StringRedisTemplate使用默认序列化方式存值区别在哪?仍然使用如下代码,只不过自己不设置序列化使用默认值

@Test
public void redisTemplateAndStringRedisTemplate1() {
    redisTemplate.opsForValue().set("redisTemplateListKey","abc");
    stringRedisTemplate.opsForValue().set("stringRedisTemplateListKey","def");
}

结果如下:

可以发现stringRedisTemplate存入的还是字符串样式,能直接看出属性值为def,然而RedisTemplate存入的key值前面居然多加了一串16进制的字符串值,同时存入redis的结果也是转换为字节数组bytes之后的看不懂的值。

stringRedisTemplate

RedisTemplate

问题5:.RedisTemplate和StringRedisTemplate存入redis的字符串类型不一致?

答案:区别在于RedisTemplate存入redis的字符串有双引号,而StringRedisTemplate存入redis的字符串居然没有双引号。

代码如下:

@Test
public void redisTemplateAndStringRedisTemplate1() {
    redisTemplate.opsForValue().set("redisTemplateListKey","abc");
    stringRedisTemplate.opsForValue().set("stringRedisTemplateListKey","def");
}

结果展示如下: RedisTemplate

StringRedisTemplate

问题6:两者的关系是StringRedisTemplate继承RedisTemplate。RedisTemplate是一个泛型类,而StringRedisTemplate则不是。

源码分析:

先看 StringRedisTemplate:

StringRedisTemplate 是继承 RedisTemplate的,一般来说子类继承父类,应该能实现更多的功能,但是此处我们发现 StringRedisTemplate 继承的是 RedisTemplate的泛型类,指定了String-String的泛型!故功能只专注于String类型!

这下就一目了然了!

再看 RedisTemplate:

问题7:为啥RedisTemplate 需要自定义序列化?

答案:RedisTemplate 可以接收任意的 Object 作为值写入 Redis,只不过写入前会把 Object 序列化为字节形式,默认采用 JDK 序列化。但是这种方式有两个缺点:

  • 可读性差。对键值对进行了序列化,中文字符串序列化后的内容表示为 16 进制表示的数据,
  • 可读性差。内存空间占用大。存储了额外的对象的类型信息,占用了内存空间。

因此,RedisTemplate 需要自定义序列化方式

问题8:对redis的value使用序列化方式有几种?

答案:4种:字符串序列化、json序列化、jdk序列化
JdkSerializationRedisSerializer、StringRedisSerializer、GenericJackson2JsonRedisSerializer、GenericFastJsonRedisSerializer。
其中:StringRedisSerializer =》 字符串序列化
JdkSerializationRedisSerializer =》 jdk序列化
GenericJackson2JsonRedisSerializer和GenericFastJsonRedisSerializer =》 json序列化

三、案例:springboot整合redis五种数据结构API

  • string(字符串)类型
  • hash(哈希)类型
  • list(列表)类型
  • set(无序集合)类型
  • zset(有序集合)类型

pom依赖

<!--redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>
<!--redis-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.6</version>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.10.1</version>
</dependency>

环境变量配置,redis采用windows的客户端启动,链接本地

#redis
spring.redis.database=15
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.passWord=
spring.redis.pool.max-active=200
spring.redis.jedis.pool.max-wait= -1
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.min-idle=0
spring.redis.timeout = 10000

User实体

package com.example.demo.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    //姓名
    private String name;
    //密码
    private String password;
}

1、string(字符串)类型

使用场景:key-value缓存、计数
操作对象:redisTemplate.opsForValue()
添加数据:set(Object k, Object v);
获取数据:get(Object k);
获取数据长度:size(Object k);
拼接内容:append(Object k, String s);
数值加一:increment(Object k);
数值减一:decrement(Object k);

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DemoApplication;
import com.example.demo.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisControllerTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	//string类型添加
    @Test
    public void stringAdd() {
        // 添加redis 字符类型数据 strKey1
        redisTemplate.opsForValue().set("strKey1","一段话。。。");

        // 添加redis 字符类型数据 strKey2
        JSONObject json = new JSONObject();
        json.put("dog","狗");
        json.put("cat","猫");
        redisTemplate.opsForValue().set("strKey2",json.toJSONString());
    }
    //string类型查询
    @Test
    public void stringQuery() {
        // 通过 strKey1 获取并打印值
        System.err.println(redisTemplate.opsForValue().get("strKey1"));
        // 通过 strKey2 获取并打印值
        System.err.println(redisTemplate.opsForValue().get("strKey2"));
    }

2、hash(哈希)类型

使用场景:缓存对象(string类型也可以实现-值存json对象字符串)
操作对象:redisTemplate.opsForHash()
添加数据:put(Object h, Object hk, Object hv);
获取map对象某值:get(Object h, Object o);
获取map对象:entries(Object h);

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DemoApplication;
import com.example.demo.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisControllerTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	//hash类型添加
    @Test
    public void hashAdd() {
        // 添加数据
        redisTemplate.opsForHash().put("hash1","key1","value1");
        redisTemplate.opsForHash().put("hash1","key2","value2");
    }
    //hash类型查询
    @Test
    public void hashQuery() {
        // 通过 h1 获取值
        System.err.println(redisTemplate.opsForHash().get("hash1","key1"));
        System.err.println(redisTemplate.opsForHash().entries("hash1"));
    }

3、list(列表)类型

使用场景:队列、栈(左进右出:队列,左进左出:栈)
操作对象:redisTemplate.opsForList()
从列表左侧添加数据:leftPush(Object k, Object v);
从列表左侧取数据:leftPop(Object k);
从列表右侧取数据:rightPop(Object k);

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DemoApplication;
import com.example.demo.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisControllerTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	//list类型添加
    @Test
    public void listAdd() {
        List list = new ArrayList<>();
        User user1 = new User("老赵", "123");
        User user2 = new User("老曹", "456");
        list.add(user1);
        list.add(user2);
        // 直接添加list
        redisTemplate.opsForList().leftPush("listKey",list);

        //循环添加元素
        redisTemplate.opsForList().leftPush("list1","v1");
        redisTemplate.opsForList().leftPush("list1","v2");
        redisTemplate.opsForList().leftPush("list1","v3");
    }
    //list类型查询
    @Test
    public void listQuery() {
        System.err.println(redisTemplate.opsForList().leftPop("listKey"));
        // 通过 list1 从队列左侧取出并删除数据
        System.err.println(redisTemplate.opsForList().leftPop("list1"));
        // 通过 list1 从队列右侧取出并删除数据
        System.err.println(redisTemplate.opsForList().rightPop("list1"));
    }

4、set(无序集合)类型

使用场景:无序且不重复的集合,求交、差、并集
操作对象:redisTemplate.opsForSet()
获取两个集合的交集:intersect(Object k, Object k1);
获取两个集合的差集:difference(Object k,Object k1);
获取两个集合的并集:uNIOn(Object k,Object k1);

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DemoApplication;
import com.example.demo.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisControllerTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	//set(无序集合)类型添加
    @Test
    public void setAdd() {
        User user1 = new User("老赵", "123");
        User user2 = new User("老曹", "456");
        // 添加数据
        redisTemplate.opsForSet().add("set1","v1","v2","v3");
        redisTemplate.opsForSet().add("set2","v1");
        redisTemplate.opsForSet().add("set3",user1, user2);
    }
    //set(无序集合)类型查询
    @Test
    public void setQuery() {
        // 求交集
        System.err.println(redisTemplate.opsForSet().intersect("set1","set2"));
        // 求差集
        System.err.println(redisTemplate.opsForSet().difference("set1","set2"));
        // 求并集
        System.err.println(redisTemplate.opsForSet().union("set1","set2"));
        System.err.println(redisTemplate.opsForSet().members("set3"));
    }

5、zset(有序集合)类型

使用场景:根据权重获取集合
操作对象:redisTemplate.opsForZSet()
添加数据:add(Object k, Object v, Object v1);
根据权重范围获取集合:rangeByScore(Object k,Object v,Object v1);

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DemoApplication;
import com.example.demo.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisControllerTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

	//zset(有序集合)类型添加
    @Test
    public void zsetAdd() {
        // 添加数据
        redisTemplate.opsForZSet().add("zset1","A",1);
        redisTemplate.opsForZSet().add("zset1","B",3);
        redisTemplate.opsForZSet().add("zset1","C",2);
        redisTemplate.opsForZSet().add("zset1","D",5);
    }
    //zset(有序集合)类型查询
    @Test
    public void zsetQuery() {
        System.err.println(redisTemplate.opsForZSet().rangeByScore("zset1",1,4));
    }

6、删除key

//删除key
@Test
public void deleteKey() {
    //删除key
    redisTemplate.delete("strKey1");
}

四、总结:

当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。

 到此这篇关于浅谈RedisTemplate和StringRedisTemplate的区别 的文章就介绍到这了,更多相关RedisTemplate和StringRedisTemplate的区别 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅谈RedisTemplate和StringRedisTemplate的区别

本文链接: https://www.lsjlt.com/news/150933.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作