Java client for Redis

insert image description here

1. Java client of Redis

The following are the top five Java clients recommended by redis.io official website
insert image description here

Java client features
Jedis Using the Redis command as the method name, the learning cost is low, simple and practical, but the Jedis instance is not thread-safe, and it needs to be used based on the connection pool in a multi-threaded environment
lettuce Lettuce is implemented based on Netty, supports synchronous, asynchronous and responsive programming, and is thread-safe. Support Redis sentinel mode, cluster mode and pipeline mode
Redisson Redisson is a distributed and scalable Java data structure collection based on Redis. Contains many powerful tools such as Map, Queue, Lock, Semaphore, AtomicLong, etc.

2. Jedis

Create a Maven project
insert image description here
1.pom.xml to introduce jedis dependencies, and by the way, also introduce junit dependencies:

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

2. Establish connection:
insert image description here
3. Test

@Test
    void testString() {
    
    
        // 往redis插入数据
        String result = jedis.set("name","zd");
        System.out.println("result = " + result);
        // 获取数据
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }

4. Release resources:

@AfterEach
    void tearDown() {
    
    
        if(jedis != null) {
    
    
            jedis.close();
        }
    }

insert image description here
Let's operate a Hash type again:

@Test
    void testHash() {
    
    
        // 插入 Hash 数据
        jedis.hset("user:1","name","zd");
        jedis.hset("user:1","age","18");
        // 获取 Hash 数据
        Map<String, String> map = jedis.hgetAll("user:1");
        System.out.println(map);
    }

Jedis connection pool

Jedis itself is not thread-safe, and frequently creating and destroying connections will cause performance loss, so we recommend that you use the Jedis connection pool instead of the direct connection method of Redis

Write the tool class of Redis:

public class JedisConnectionFactory {
    
    
    private static final JedisPool jedisPool;

    static {
    
    
        // 配置连接池
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(8);
        jedisPoolConfig.setMaxIdle(8);
        jedisPoolConfig.setMinIdle(0);
        jedisPoolConfig.setMaxWaitMillis(1000);
        // 创建连接池对象
        jedisPool = new JedisPool(jedisPoolConfig,
                "127.0.0.1",6379,1000,"123456");
    }
    
    public static Jedis getJedis() {
    
    
        return jedisPool.getResource();
    }
}

insert image description here
insert image description here
When we go to close() again, it is not really closed, but the resource is returned to the Redis connection pool, and it is
insert image description here
no problem for us to execute it again

3. Spring Data Redis

SpringData is a data operation module in Spring, including the integration of various databases. The integration module for Redis is called SpringDataRedis, the official website address: Spring Data
insert image description here
Spring Data Redis has the following characteristics:

  • Provides integration of different Redis clients (Lettuce and Jedis)
  • Provides RedisTemplate unified API to operate Redis
  • Support Redis publish-subscribe model
  • Supports Redis Sentinel and Redis Cluster
  • Support Responsive Programming based on Lettuce
  • Supports data serialization and deserialization based on JDK, JSON, strings, and Spring objects
  • Support Redis-based JDKCollection implementation

Spring Data Redis Quick Start

The RedisTemplate tool class is provided in SpringDataRedis, which encapsulates various operations on Redis. And encapsulate the operation API of different data types into different types

API return value illustrate
redisTemplate.opsForValue() ValueOperations Operate String type data
redisTemplate.opsForHash() HashOperations Operate Hash type data
redisTemplate.opsForList() ListOperations Operate List type data
redisTemplate.opsForSet() SetOperations Operate Set type data
redisTemplate.opsForZSet ZSetOperations Operate SortedSet type data
redisTemplate Operate common commands

Our SpringBoot already provides support for SpringBootRedis, which is very simple to use:
1. Introduce dependencies:

<!--Redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--连接池依赖-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2. Configuration file:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    lettuce:
      pool:
        max-active: 8 #最大连接
        max-idle: 8 #最大空闲连接
        min-idle: 0 #最小空闲连接
        max-wait: 1000 #连接等待时间

3. Inject the RedisTemplate object and write the test code:

@SpringBootTest
class SpringDataRedisDemoApplicationTests {
    
    

    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void contextLoads() {
    
    
        // 写入一条String数据
        redisTemplate.opsForValue().set("name","小王");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
}

insert image description here

SpringDataRedis serialization method

insert image description hereWhy is it that we have already operated, but the name in Redis has not been modified?
RedisTemplate can receive any Object as a value and write it to Redis, but it will serialize the Object into bytes before writing. The default is JDK serialization, and the result is as follows:

insert image description here
There are some problems with this:Poor readability and large memory usage

insert image description here
We can customize the serialization method of RedisTemplate:

@Configuration
public class RedisConfig {
    
    

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    
    
        // 创建RedisTemplate对象
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回 RedisTemplate对象
        return template;
    }
}

insert image description here
insert image description here
We found that an error was reported because we did not introduce jackson dependencies:

<!--Jackson依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

insert image description here
The execution is successful, let's take a look at the Redis database again
insert image description here
. The string is ok, let's try to see if the object can be serialized correctly for us

// 创建一个Sudent类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    
    
    private String name;
    private Integer age;
}

test:

@Test
    void testSaveStudent() {
    
    
        // 写入数据
        redisTemplate.opsForValue().set("student",new Student("小王",18));
        //获取数据
        Student student = (Student) redisTemplate.opsForValue().get("student");
        System.out.println("student: " + student);
    }

insert image description here
insert image description here
We can find that when we save the object, it helps us serialize it into a Json string, and when we fetch the data, it helps us deserialize it into a Java object, but in this way, the Json serializer will write the class type of the class into the json result. Entering Redis will bring additional memory overhead

In order to save memory space, we will not actually use the JSON serializer to process the value, but use the String serializer uniformly, requiring only the key and value of the String type to be stored. When it is necessary to store Java objects, it must be done manually
insert image description here

StringRedisTemplate

Spring provides a StringRedisTemplate class by default, and the serialization method of its key and value is String by default. save us

@Autowired
    private StringRedisTemplate stringRedisTemplate;
    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void testStringRedisTemplate() throws JsonProcessingException {
    
    
        Student student = new Student("小王",18);
        // 手动序列化
        String json = mapper.writeValueAsString(student);
        // 写入数据到redis
        stringRedisTemplate.opsForValue().set("student",json);
        //读取数据
        String val =  stringRedisTemplate.opsForValue().get("student");
        // 手动反序列化
        Student student1 = mapper.readValue(val,Student.class);
        System.out.println("student1: " + student1);
    }

insert image description here
insert image description here
Two serialization methods of RedisTemplate:
Method 1:

  1. Custom RedisTemplate
  2. Modify the serializer of RedisTemplate to GenericJackson2JsonRedisSerializer

Method 2:

  1. Use StringRedisTemplate
  2. When writing to Redis, manually serialize the object to JSON
  3. When reading Redis, manually deserialize the read JSON into an object

Hash operation

insert image description here

We can find that when we want to operate the Hash type, we find that there is no hset() method, because we are using a map operation similar to Java.
insert image description here

put is equivalent to hset, putAll is equivalent to hmset
insert image description here

Other methods are similar

@Test
    void testHash() {
    
    
        stringRedisTemplate.opsForHash().put("student","name","小王");
        stringRedisTemplate.opsForHash().put("student","age","18");
        Map<Object, Object> student = stringRedisTemplate.opsForHash().entries("student");
        System.out.println("student: " + student);
    }

insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/buhuisuanfa/article/details/131580119