Jedis使用操作

一:简介

  在浏览本篇文章时务必要会Redis的基本命令,因为在一些主流语言中使用一些其它Redis客户端时都是基于基本命令来操作的;比如在java项目中使用连接Redis客户端有Jedis、Redisson、Jredis、JDBC-Redis;不过官方推荐我们使用Jedis和Redisson;本文章中我会使用Jedis和SpringDataRedis来操作远程的Redis服务端。

  Jedis封装了Redis的一些命令操作,它是Redis的Java客户端,和我们在Redis自带的客户端输入的命令一样,Jedis也提供了连接池管理,可以不用每次关闭连接Redis而消耗时间。

  SpringDataRedis是Spring大家族的一部分,提供了在Spring应用中通过简单的配置访问Redis服务,对Redis底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅等,不过在高版本中SpringDataRedis底层则不在使用Jedis。(后续介绍SpringDataRedis)

1:务必看看

  注:本篇文章的命令都在我之前的 【Redis命令】 一文中都详细说明了,我也是参照那篇文章转换为Java程序来实现;遇到不会的命令只须参照【Redis命令】一文 Ctrl+F 直接搜索那个命令即可;而且使用Jedis只要找到你需要的方法,方法参数和官方命令顺序都是一样的,而且简单易上手,主要是知道某个命令干啥的就行;还有就是我的文章只是参考,具体的大家可以参考官方文档!

二:Jedis继承关系分析

1:Jedis类

  Jedis提供了Redis客户端的连接和命令查询,从Jedis继承关系中发现它实现很多的命令接口,每个接口都定义了不同的操作形式,这符合面向对象开发原则中的接口隔离原则和单一职责原则。下面的接口声明了相关的redis命令操作,每个接口都负责对一部分的命令进行方法声明

Jedis使用操作

Jedis父类BinaryJedis所依赖的接口:
    BasicCommands:
        提供基础的查询命令,如ping,quit,flushdb
    BinaryJedisCommands:
        提供了针对redis数据结构的CURD等操作,其中参数(K-V)必须以byte数组形式提供
    MultiKeyBinaryCommands:
        提供了针对redis数据结构的CURD等批量操作,其中参数(K-V)必须以byte数组形式提供
    AdvancedBinaryJedisCommands:
        提供高级操作redis的命令,如config相关,slowlog,client等命令,其中参数(K-V)必须以byte数组形式提供
    BinaryScriptingCommands:
        提供Lua脚本运行命令,命令必须以byte数组形式提供。
Jedis所依赖的接口:
    JedisCommands:
        提供了针对redis数据结构的CURD等操作,其中参数(K-V)必须以String形式提供
    MultiKeyCommands:
        提供了针对redis数据结构的CURD等批量操作,其中参数(K-V)必须以String数组形式提供
    AdvancedJedisCommands:
        提供高级操作redis的命令,如config相关,slowlog,client等命令,其中参数(K-V)必须以String形式提供
    ScriptingCommands:
        提供Lua脚本运行命令,命令必须以String形式提供。
    BasicCommands:
        提供如ping,quit,flushDb运维类命令
    ClusterCommands:
        提供集群状态查看,集群操作的命令
    SentinelCommands:
        提供哨兵操作命令
    ModuleCommands:
        提供redis模块加载和卸载命令

2:Client类

  除了方法接口声明之外,Jedis还提供了客户端Client,使用该类仍然可以连接Redis服务端并进行相关的命令操作。Client本身只是提供相关的命令方法,这些方法声明定义在Commands接口,连接操作则定义在Connection类,也就是说Client类类似于一个前台,可以提供各种服务,而具体的实现则依赖于Connection和Commands,Client提供方法与Jedis基本一致,不同的是Client类里获取命令是没有返回值的,所有我们一般不用Client,都是使用Jedis,不过Jedis底层必须有Client的存在

Client所依赖的接口:
    Commands:
        内部都是Redis基本命令的封装
Client所继承的类:
    BinaryClient:
        用来最终和Redis服务端交互的客户端,以二进制交互,内部继承Connection类

3:Jedis如何发送命令到Redis服务端

Jedis使用操作

  Jedis是通过Socket对Redis服务端进行连接的,而Jedis和Client本身并没有Socket连接方法的实现,相关的连接方法都在Connection类中,观察继承关系,Connection类是其顶层的实现类。Jedis或者Client发送命令时,必须通过Connection类的connect()方法建立TCP连接。
  在使用Connection类时,需提供相关的参数进行实例化,从构造方法可以看到,需要提供主机名,如果不设置,则使用默认名localhost.连接端口,不设置则使用默认端口6379,连接超时时长(如果不进行设置,则默认与socketTimeout保持一致),Socket读取超时时长(如果不进行设置,则使用默认时长2000ms),SSL加密传输则是可选的。在连接时必须判断当前对象的连接状态,如果符合条件则新建Socket实例。
  Jedis和Client类通过Connection对象的sendCommand()方法进行命令传输,在传输命令时必须将字符串转为字节数组,如果类似于ping,ask这样的命令,只需要将命令转为字节即可。转换完成之后写入到输出流中,将字节流发送给Redis 服务端。

三:Jedis操作使用

1:基本案例

  基本案例中我使用maven的一个空项目(maven骨架:maven-archetype-quickstart)来进行简单的操作;

  <!--导入Jedis坐标,用来操作Redis的,主要就这个包-->
  <dependencies>
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.7.0</version>
    </dependency>
    <!--导入fastjson,用于对象的转换JSON格式-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.78</version>
    </dependency>
  </dependencies>
public static void main(String[] args){
    //创建一个连接
    Jedis jedis = new Jedis("localhost", 6379);
    //ping一下Redis服务端是否在线,成功则返回 “PONG” 反之报错超时
    String ping = jedis.ping();
    //Jedis它实现了各式各样接口,最终汇聚一个类Jedis,它内部封装了全部Redis命令
    //比如下面的”String类型命令set“保存两条数据,保存成功则返回ok
    jedis.set("name","zhangsan");
    jedis.set("age","22");
    //在redis中获取name值
    String name = jedis.get("name");
    System.out.println(name);
    jedis.close();//关闭连接
    
    //也可以直接使用Client,但是我们还是使用Jedis吧,让Jedis底层调用Client吧,我们直接使用是没有返回值的
    Client client = new Client("localhost", 6379);
    client.set("name","lisi");
    client.close();
}

2:Jedis连接池

Jedis使用操作
#最大活动对象数
redis.pool.maxTotal=1000
#最大能够保持idel状态的对象数
redis.pool.maxIdle=100
#最小能够保持idel状态的对象数
redis.pool.minIdle=50
#当池内没有返回对象时,最大等待时间
redis.pool.maxWaitMillis=10000
#当调用borrow Object方法时,是否进行有效性检查
redis.pool.testOnBorrow=true
#当调用return Object方法时,是否进行有效性检查
redis.pool.testOnReturn=true
#“空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1
redis.pool.timeBetweenEvictionRunsMillis=30000
#向调用者输出“链接”对象时,是否检测它的空闲超时
redis.pool.testWhileIdle=true
# 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3
redis.pool.numTestsPerEvictionRun=50
#redis服务器的IP
redis.ip=localhost
#redis服务器的Port
redis.port=6379
#连接Redis超时时间秒
redis.timeout=2000
#连接Redis的password,不写则没有密码
redis.password=
jedisPool.properties Jedis使用操作
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Properties;

/**
 * @Author AnHui_XiaoYang
 * @Email 939209948@qq.com
 * @Date 2021/10/17 20:44
 * @Description Jedis连接池工具
 */
public class JedisPoolUtils {
    private static JedisPool jedisPool;

    static {
        //类加载时,读取配置文件
        InputStream in = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedisPool.properties");
        //创建Properties对象并关联对象
        Properties pro = new Properties();
        try {
            pro.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //创建连接池配置并设置值
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(pro.getProperty("redis.pool.maxTotal")));
        config.setMaxIdle(Integer.parseInt(pro.getProperty("redis.pool.maxIdle")));
        config.setMinIdle(Integer.parseInt(pro.getProperty("redis.pool.minIdle")));
        config.setMaxWaitMillis(Long.parseLong(pro.getProperty("redis.pool.maxWaitMillis")));
        config.setTestOnBorrow(Boolean.parseBoolean(pro.getProperty("redis.pool.testOnBorrow")));
        config.setTestOnReturn(Boolean.parseBoolean(pro.getProperty("redis.pool.testOnReturn")));
        Duration duration = Duration.ofMinutes(Long.parseLong(pro.getProperty("redis.pool.timeBetweenEvictionRunsMillis")));
        config.setTimeBetweenEvictionRuns(duration);
        config.setTestWhileIdle(Boolean.parseBoolean(pro.getProperty("redis.pool.testWhileIdle")));
        config.setNumTestsPerEvictionRun(Integer.parseInt(pro.getProperty("redis.pool.numTestsPerEvictionRun")));
        String host = pro.getProperty("redis.ip");
        Integer port = Integer.valueOf(pro.getProperty("redis.port"));
        Integer timeout = Integer.valueOf(pro.getProperty("redis.timeout"));
        String password = pro.getProperty("redis.password");
        if (password == null || "".equals(password))
            jedisPool = new JedisPool(config, host, port, timeout);
        else
            jedisPool = new JedisPool(config, host, port, timeout, password);
    }

    /**
     * @return 返回一个JedisClient
     */
    public static Jedis getJedisClient() {
        return jedisPool.getResource();
    }
}
JedisPoolUtil连接工具类
    public static void main(String[] args) {
        //平时使用连接池对象即可,每次都重新创建获取会消耗大量时间
        Jedis jedis = JedisPoolUtils.getJedisClient();
        jedis.set("name","zhangsan");
        String s = jedis.get("name");
        System.out.println(s);
        jedis.close();//不用时直接close即可
    }

  总结:现在在项目中一般不会单独引用Jedis了,通常会以SpringBoot集成Redis,通过RedisTemplate模板来操作Redis;具体使用请参考 SpringDataRedis入门到深入

上一篇:【3】influxdb2-2.1.1 C#创建Buckets、插入数据


下一篇:amdp client/filter/sql