We have studied the Redis command line client redis-CLI, next let’s look at the Redis Java programming language based client.

In Java, there are three common Redis clients, Jedis, Redisson and Lettuce. The three have their own characteristics and applicable scenarios.

  • Jedis: Redis Java implementation client, its API provides a more comprehensive Redis command support;

    Method call in Jedis is relatively low-level exposed Redis API, that is, Java method in Jedis is basically consistent with Redis API, understand Redis API, also can skillfully use Jedis.

  • Redisson: Implements distributed and extensible Java data structures, provides many distributed operations services, such as distributed locks, distributed collections, and delay queuing via Redis. Compared with Jedis, the function is relatively simple, does not support string operations, does not support sorting, transaction, pipeline, partition and other Redis features. The goal of Redisson is to promote a separation of focus from Redisso that users can focus more on processing business logic.

    Methods in Redisson are more abstract, and each method call may make one or more Redis method calls.

  • Lettuce: Advanced Redis client for thread-safe synchronization, asynchronous and response use, supporting clustering, Sentinel, pipes and encoders. Is the default client for SpringBoot2.x.

Ok, let’s start learning how to use Jedis.

1. Basic use of Jedis

Create a Maven project and add Jedis dependencies to the project.

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.82.</version>
        </dependency>
Copy the code

Jedis is very simple to use, with just three lines of code to implement the basic set/get functionality:

        //1. Generate a Jedis object that communicates with the specified Redis instance
        Jedis jedis = new Jedis("127.0.0.1".6379);
        // 2. Jedis executes the set operation
        jedis.set("hello"."world");
        //3. Jedis execute get,value="world"
        String value = jedis.get("hello");
Copy the code

To initialize Jedis, you need two parameters: the IP and port of the Redis instance. In addition to these two parameters, there is a four-parameter constructor that is commonly used:

Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout)
Copy the code

Parameter Description:

  • Host: IP address of the machine where the Redis instance resides
  • Port: port of the Redis instance
  • ConnectionTimeout: Client connection times out
  • SoTimeout: Read/write timeout of the client

You can print the result of the above program:

Similar to JDBC, operations that generally involve network I/O are best done using the try catch finally form, slightly modifying the above example:

        Jedis jedis = null;
        try {
            jedis = new Jedis("127.0.0.1".6379);
            jedis.get("hello");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(jedis ! =null) { jedis.close(); }}Copy the code

Let’s look at how Jedis operates on various basic data types:

  • string
        jedis.set("hello"."world");
        / / the world
        System.out.println(jedis.get("hello"));
       1 / / results
        System.out.println(jedis.incr("counter"));
Copy the code

  • hash
        jedis.hset("myhash"."f1"."v1");
        jedis.hset("myhash"."f2"."v2");
        {f2=v2, f1=v1}
        System.out.println(jedis.hgetAll("myhash"));
Copy the code
  • list
        jedis.rpush("mylist"."1");
        jedis.rpush("mylist"."2");
        jedis.rpush("mylist"."3");
        // Run result [1, 2, 3]
        System.out.println(jedis.lrange("mylist".0, -1));
Copy the code
  • set
        jedis.sadd("myset"."a");
        jedis.sadd("myset"."b");
        jedis.sadd("myset"."a");
        // Result [b, a]
        System.out.println(jedis.smembers("myset"));
Copy the code
  • zset
        Jedis jedis = new Jedis("127.0.0.1".6379);
        jedis.zadd("thezset".99."tom");
        jedis.zadd("thezset".66."peter");
        jedis.zadd("thezset".33."james");
        // James 33.0 Peter 66.0 Tom 99.0
        jedis.zrangeWithScores("thezset".0, -1).stream().forEach(s->{
            System.out.print(s.getElement()+""+s.getScore()+"");
        });
Copy the code

2. Serialization

In Java, stored objects are generally serialized and deserialized, and Jedis itself does not support serialization. You can introduce third-party serialization tools for games, such as XML, Json, Google’s Protobuf, Facebook’s Thrift, and so on.

Let’s take Protostuff (Java client for Protobuf) as an example:

  • Introduce protostuff dependencies
   <properties>
        <protostuff.version>1.011.</protostuff.version>
    </properties>
    
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>${protostuff.version}</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>${protostuff.version}</version>
        </dependency>    
Copy the code
  • Defining entity Classes
public class Club implements Serializable {
    private int id; // id
    private String name; / / name
    private String info; / / description
    private Date createDate; // Creation date
    private int rank; / / no
    // omit getters/setters, etc
}    
Copy the code
  • Test serialization and deserialization
        // 1. Generate the serialization utility class
        ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();
        // 2. Generate the Jedis object
        Jedis jedis = new Jedis("127.0.0.1".6379);
        // serialize
        String key = "club:1";
        // Define entity objects
        Club club = new Club(1."AC"."Milan".new Date(), 1);
        / / the serialization
        byte[] clubBtyes = protostuffSerializer.serialize(club);
        jedis.set(key.getBytes(), clubBtyes);
        // 4. Deserialize
        byte[] resultBtyes = jedis.get(key.getBytes());
        Club resultClub = protostuffSerializer.deserialize(resultBtyes);
        // result Club{id=1, name='AC', info=' AC', createDate=Sat May 15 22:21:42 CST 2021, rank=1}
        System.out.println(resultClub.toString());
Copy the code

3. Jedis connection pool

Above, we use Jedis direct connection mode. Each time, we create a TCP connection and disconnect the connection after using it.

This process of frequent connection/disconnection is clearly a waste of resources.

As with database connection pooling, you can also introduce pooling techniques to store Jedis connections in a JedisPool and fetch them each time you go to the pool instead of recreating them.

Connection pooling is done in such a way that Jedis connections can be pre-initialized, so you only need to borrow from the Jedis connection pool each time. Borrowing and returning operations are performed locally, with a small concurrent synchronization overhead, much less than the overhead of creating a new TCP connection.

Jedis provides the JedisPool class as a connection pool for Jedis, and uses Apache’s common object pool tool as a resource management tool.

The following is an example of Redis using JedisPool:

1) Jedis connection pool (usually JedisPool is singleton) :

        // common-pool connection pool configuration. The default configuration is used
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        // Initialize the Jedis connection pool
        JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1".6379);
Copy the code

2) The Jedis object is not directly generated by a Jedis object for direct connection, but directly obtained from the connection pool:

        Jedis jedis = null;
        try {
            // 1. Get the Jedis object from the connection pool
            jedis = jedisPool.getResource();
            // 2. Perform operations
            jedis.get("hello");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(jedis ! =null) {
                // If JedisPool is used, the close operation does not close the connection, which means return the connection pooljedis.close(); }}Copy the code

GenericObjectPoolConfig uses the default configuration and actually provides many parameters, such as maximum number of connections in the pool, maximum number of free connections, minimum number of free connections, connection activity detection, and so on.





Reference:

[1] : Redis Development and Operation

[2] : Redis several Java client comparison