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 里找)

<!--引入Jedis依赖-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.2.0</version>
</dependency>

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

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

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

 @Test
    void contextLoads() {
        // 1.往redis中存放一条String类型的数据并获取返回结果
        String result = jedis.set("11", "xxxxxxx");
        System.out.println("result = " + result);

        // 2.从redis中获取一条数据
        String url = jedis.get("11");
        System.out.println("url = " + url);
    }

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

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

 结果:成功无报错

2 Jedis连接池 

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

  同样导入依赖

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
</dependency>

 配置文件

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

配置类

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

package com.example.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class redisconfig {
    private final Logger logger = LoggerFactory.getLogger(redisconfig.class);

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.jedis.timeout}")
    private int timeout;
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;

    @Bean
    public JedisPool jedisPool(){
        JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMinIdle(minIdle);

        JedisPool jedisPool =new JedisPool(jedisPoolConfig,host,port,timeout,password);
        logger.info("jedisPool连接成功:"+host+"\t"+port);
        return jedisPool;
    }
}

   测试:

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

 

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

@Service
@Log
public class UserServiceImpl implements UserService {

    @Autowired
    private JedisPool jedisPool;    //Jedis连接池
    /**
     * Redis String 类型
     * 需求:用户输入一个key
     * 先判断Redis中进行查询
     *  如果存在,在Redis中进行查询
     *  如果不存在,在Mysql查询,将结果赋给Redis,并返回
     */
    @Override
    public String getString(String key) {
        String val=null;
        //获取jedis
        Jedis jedis = jedisPool.getResource();
        //判断jedis是否存在
        if(jedis.exists(key)){
            log.info("查询Redis中的数据");
            val= jedis.get(key);
        }else {
            String sql ="java培训班";
            log.info("查询的是musql数据库");
            val= jedis.set(key,sql);
        }
        //关闭连接
        jedis.close();
        return val;
    }
}

结果:

 测试通过

 

 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操作一下:

然后引入连接池依赖

<!--连接池依赖-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

编写配置文件application.yml

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

   编写测试类执行测试方法

   

  @Resource
    private RedisTemplate redisTemplate;
    @Test
    void contextLoads() {
        ValueOperations string = redisTemplate.opsForValue();

        string.set("林青霞","周杰伦");
//        Object o = string.get("林青霞");
        String s = (String) string.get("林青霞");
        System.out.println(s);

    }

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

结果:

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

RedisSerializer配置来解决:

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

缺点:

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

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

 

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        // 1.创建RedisTemplate对象
        RedisTemplate<String ,Object> redisTemplate = new RedisTemplate<>();
        // 2.设置连接工厂
        redisTemplate.setConnectionFactory(factory);

        // 3.创建序列化对象
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

        // 4.设置key和hashKey采用String的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        // 5.设置value和hashValue采用json的序列化方式
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);

        return redisTemplate;
    }
}

 这个代码可以让我们的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的过程

 

package com.example.demo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
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.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;

@SpringBootTest
public class stringredistemplatetest {
    //准备工作 准备一个json序列化对象 一个Stringredistemplated对象
      private static  final ObjectMapper objectMapper = new ObjectMapper();
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void test() throws JsonProcessingException {
        user user=new user("ll","123456789");
        //手动序列化(user->json串)
        String string = objectMapper.writeValueAsString(user);
        //操作string类型的Apl
        ValueOperations<String, String> s  = stringRedisTemplate.opsForValue();
        //存入测试数据
       s.set("user1",string);
        //查询存入的数据
        String user1 = s.get("user1");
        //反序列化(json串-> user)
        com.example.demo.user user2 = objectMapper.readValue(user1, com.example.demo.user.class);
        System.out.println(user1);
    }
}

 查看结果

 

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

总结:

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

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

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

提示:

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

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

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值