当前位置:   article > 正文

Redis客户端(超级详细)

redis客户端

    redis安装完成,了解了redis的基本的命令。我们就可以操作Redis,实现数据的CRUD了。这需要用到Redis客户端,包括:

  • 命令行客户端
  • 图形化桌面客户端
  • 编程客户端

1 命令行客户端

   这个客户端是安装完redis一个自带的客户端在启动完毕redis后可以使用 redis-cli 这一命令打开

redis-cli [options] [commonds]
  • 其中常见的options有:

    • -h 127.0.0.1:指定要连接的redis节点的IP地址,默认是127.0.0.1
    • -p 6379:指定要连接的redis节点的端口,默认是6379
    • -a 132537:指定redis的访问密码
  • 其中的commonds就是Redis的操作命令,例如:

    • ping:与redis服务端做心跳测试,服务端正常会返回pong
    • 不指定commond时,会进入redis-cli的交互控制台:

一般是不会指定具体的命令,方便直接进入控制台做一些命令

 2 连接

GitHub上的大神编写了Redis的图形化桌面客户端,地址:https://github.com/uglide/RedisDesktopManager

不过该仓库提供的是RedisDesktopManager的源码,并未提供windows安装包。

又有一位大佬把这个大神的每一个版本都做好了了安装包。地址:https://github.com/lework/RedisDesktopManager-Windows/releases

安装就一直无脑下一步就行了

      安装完之后连接:  这里分享我踩过的一个坑 在连接时一直超时,一步步查看redis是否启动,redis的配置文件,网络是否能ping通,防火墙也没有显示出有关redis的拦截。但是就是连接不上。我通过ss命令查看与6379这个redis的端口通信的进程发现没有找到。我试着把防火墙关了结果成功了。 (systemctl stop firewalld) 

    一步步查看redis的问题可能:
 http://systemctl stop firewalld

如何连接到Redis 

3.Java客户端 

    1 Jedis快速入门

    创建一个空的spring boot Module  导入redis的第三方依赖  (可以在Maven Repository 里找)

  1. <!--引入Jedis依赖-->
  2. <dependency>
  3. <groupId>redis.clients</groupId>
  4. <artifactId>jedis</artifactId>
  5. <version>4.2.0</version>
  6. </dependency>

  在测试类里写一个在其他方法执行前执行的方法用来与redis客户端进行连接

  1. @BeforeEach //被该注解修饰的方法每次执行其他方法前自动执行
  2. void setUp(){
  3. // 1. 获取连接
  4. jedis = new Jedis("192.168.230.88",6379);
  5. // 2. 设置密码
  6. jedis.auth("132537");
  7. // 3. 选择库(默认是下标为0的库)
  8. jedis.select(0);
  9. }

 编写一个操作数据的方法(这里以操作String类型为例)

  1. @Test
  2. void contextLoads() {
  3. // 1.往redis中存放一条String类型的数据并获取返回结果
  4. String result = jedis.set("11", "xxxxxxx");
  5. System.out.println("result = " + result);
  6. // 2.从redis中获取一条数据
  7. String url = jedis.get("11");
  8. System.out.println("url = " + url);
  9. }

最后不要忘记编写一个释放资源的方法

  1. @AfterEach
  2. //被该注解修饰的方法会在每次执行其他方法后执行
  3. void tearDown() {
  4. // 1.释放资源
  5. if (jedis != null) {
  6. jedis.close();
  7. }

 结果:成功无报错

2 Jedis连接池 

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式

  同样导入依赖

  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. </dependency>

 配置文件

 这里因为涉及到yml中的数字的绑定处理,yml对数字可以按照8进制或者十六进制或十进制来处理,恰好这个2000在三个都可以显示,正常想要让它当一个十进制需要加" "来解决这个问题。这个坑可以躲避一下。

配置类

由于jedispool时第三方bean所以采用配置类的方式交给spring 管理

  1. package com.example.config;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import redis.clients.jedis.JedisPool;
  8. import redis.clients.jedis.JedisPoolConfig;
  9. @Configuration
  10. public class redisconfig {
  11. private final Logger logger = LoggerFactory.getLogger(redisconfig.class);
  12. @Value("${spring.redis.host}")
  13. private String host;
  14. @Value("${spring.redis.port}")
  15. private int port;
  16. @Value("${spring.redis.password}")
  17. private String password;
  18. @Value("${spring.redis.jedis.timeout}")
  19. private int timeout;
  20. @Value("${spring.redis.jedis.pool.max-active}")
  21. private int maxActive;
  22. @Value("${spring.redis.jedis.pool.max-idle}")
  23. private int maxIdle;
  24. @Value("${spring.redis.jedis.pool.min-idle}")
  25. private int minIdle;
  26. @Bean
  27. public JedisPool jedisPool(){
  28. JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
  29. jedisPoolConfig.setMaxIdle(maxIdle);
  30. jedisPoolConfig.setMaxTotal(maxActive);
  31. jedisPoolConfig.setMinIdle(minIdle);
  32. JedisPool jedisPool =new JedisPool(jedisPoolConfig,host,port,timeout,password);
  33. logger.info("jedisPool连接成功:"+host+"\t"+port);
  34. return jedisPool;
  35. }
  36. }

   测试:

开发中这是放在service层中的这里测试随便写的

 

 service:(jedis相当于之前的dao层做redis直接获取jedis对象调方法就可以)

  1. @Service
  2. @Log
  3. public class UserServiceImpl implements UserService {
  4. @Autowired
  5. private JedisPool jedisPool; //Jedis连接池
  6. /**
  7. * Redis String 类型
  8. * 需求:用户输入一个key
  9. * 先判断Redis中进行查询
  10. * 如果存在,在Redis中进行查询
  11. * 如果不存在,在Mysql查询,将结果赋给Redis,并返回
  12. */
  13. @Override
  14. public String getString(String key) {
  15. String val=null;
  16. //获取jedis
  17. Jedis jedis = jedisPool.getResource();
  18. //判断jedis是否存在
  19. if(jedis.exists(key)){
  20. log.info("查询Redis中的数据");
  21. val= jedis.get(key);
  22. }else {
  23. String sql ="java培训班";
  24. log.info("查询的是musql数据库");
  25. val= jedis.set(key,sql);
  26. }
  27. //关闭连接
  28. jedis.close();
  29. return val;
  30. }
  31. }

结果:

 测试通过

 

 redis服务器结果:

3  SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

官网地址Spring Data Redis

  • 提供了对不同Redis客户端的整合(LettuceJedis
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

利用spring boot操作一下:

然后引入连接池依赖

  1. <!--连接池依赖-->
  2. <dependency>
  3. <groupId>org.apache.commons</groupId>
  4. <artifactId>commons-pool2</artifactId>
  5. </dependency>

编写配置文件application.yml

  1. spring:
  2. redis:
  3. host: 192.168.230.88 #指定redis所在的host
  4. port: 6379 #指定redis的端口
  5. password: 132537 #设置redis密码
  6. lettuce:
  7. pool:
  8. max-active: 8 #最大连接数
  9. max-idle: 8 #最大空闲数
  10. min-idle: 0 #最小空闲数
  11. max-wait: 100ms #连接等待时间

   编写测试类执行测试方法

   

  1. @Resource
  2. private RedisTemplate redisTemplate;
  3. @Test
  4. void contextLoads() {
  5. ValueOperations string = redisTemplate.opsForValue();
  6. string.set("林青霞","周杰伦");
  7. // Object o = string.get("林青霞");
  8. String s = (String) string.get("林青霞");
  9. System.out.println(s);
  10. }

这里注入不能使用@Autowired 只能根据name注入使用@Resource

结果:

这个时候打开我们的RESP发现明明插入的是一个stirng类型的key-value  看到的确是乱码

RedisSerializer配置来解决:

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的

缺点:

  • 可读性差
  • 内存占用较大

那么如何解决以上的问题呢?我们可以通过自定义RedisTemplate序列化的方式来解决。

 

  1. @Configuration
  2. public class RedisConfig {
  3. @Bean
  4. public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
  5. // 1.创建RedisTemplate对象
  6. RedisTemplate<String ,Object> redisTemplate = new RedisTemplate<>();
  7. // 2.设置连接工厂
  8. redisTemplate.setConnectionFactory(factory);
  9. // 3.创建序列化对象
  10. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  11. GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  12. // 4.设置key和hashKey采用String的序列化方式
  13. redisTemplate.setKeySerializer(stringRedisSerializer);
  14. redisTemplate.setHashKeySerializer(stringRedisSerializer);
  15. // 5.设置value和hashValue采用json的序列化方式
  16. redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
  17. redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
  18. return redisTemplate;
  19. }
  20. }

 这个代码可以让我们的key采用string的序列化,而我们的value采用json的序列化(采用json的序列化必须要有json的依赖通常我们使用spring boot勾选  springmvc里自带)

再次运行结果

resp结果:
 

 利用Lombok快速创建一个bean 使用redistemplate(自定义序列后)插入一个user实体:

 

结果: 

 

 

 

尽管Json序列化可以满足我们的需求,但是依旧存在一些问题。

如上图所示,为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。

那么我们如何解决这个问题呢?我们可以通过下文的StringRedisTemplate来解决这个问题。

StringRedisTemplate(推荐使用)

 

为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化(使用json序列化对象)。

image-20220525172001057

Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程

 

  1. package com.example.demo;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import lombok.AllArgsConstructor;
  5. import org.junit.jupiter.api.Test;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.data.redis.core.StringRedisTemplate;
  9. import org.springframework.data.redis.core.ValueOperations;
  10. import javax.annotation.Resource;
  11. @SpringBootTest
  12. public class stringredistemplatetest {
  13. //准备工作 准备一个json序列化对象 一个Stringredistemplated对象
  14. private static final ObjectMapper objectMapper = new ObjectMapper();
  15. @Resource
  16. private StringRedisTemplate stringRedisTemplate;
  17. @Test
  18. void test() throws JsonProcessingException {
  19. user user=new user("ll","123456789");
  20. //手动序列化(user->json串)
  21. String string = objectMapper.writeValueAsString(user);
  22. //操作string类型的Apl
  23. ValueOperations<String, String> s = stringRedisTemplate.opsForValue();
  24. //存入测试数据
  25. s.set("user1",string);
  26. //查询存入的数据
  27. String user1 = s.get("user1");
  28. //反序列化(json串-> user)
  29. com.example.demo.user user2 = objectMapper.readValue(user1, com.example.demo.user.class);
  30. System.out.println(user1);
  31. }
  32. }

 查看结果

 

 可以看到这是redis服务器就没有class了当我们操作大量的数据是大大节省了内存空间

总结:

RedisTemplate的两种序列化实践方案,两种方案各有各的优缺点,可以根据实际情况选择使用

stringredistemplate 可以在操作大量的数据的时候推荐使用

reidstemplate操作数据量不是很多使用提高我们的开发速度

提示:

使用strinbgredistemplate插入value不是一个bean其实你可以不做序列化和反序列化,做这两个的作用是操作bean更加的简单

 stringredistemplate还提供了多个类型的操作都是用opsfor..来获取

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/454274
推荐阅读
相关标签
  

闽ICP备14008679号