Redis Tutorial (Java Version)

Use advanced blog https://blog.piaoruiqing.com/2019/06/11/redis

keywords

  • Jedis: Redis Java client implementation.
  • LettuceRedis Java client implementation, based on Netty.
  • spring-data-redis: Spring encapsulates Redis. It is simple to configure and provides an abstract encapsulation for interacting with Redis storage. It is very elegant and extensible. It can integrate Jedis, Lettuce and other redis clients. After springboot2.0, the official default integrated client is changed from Jedis to Lettuce.

preface

This article will explain the integration of Redis with Java, the use of Jedis and Lettuce will be briefly described, and the integration and use of Spring Redis will be the main content.

Jedis

Github.com/xetorthio/j…

Introducing dependencies:

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

Jedis encapsulates the redis command and is basically the same as redis cli. The following is an example of the string operation:

/** jedis pool */
private static final JedisPool POOL = new JedisPool(new JedisPoolConfig(), "test-redis-server".6379);

// test Binary-safe strings with Jedis
try (Jedis jedis = POOL.getResource()){ 
    {   // SET mykey myvalue
        String result = jedis.set("mykey"."myvalue");
        LOGGER.info("cmd: SET mykey myvalue, result: {}", result);
    }
    {   // GET mykey
        String result = jedis.get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result);
    }
    {   // KEYS my*
        Set<String> keys = jedis.keys("my*");
        LOGGER.info("cmd: KEYS my*, result: {}", JsonUtils.writeValueAsString(keys, true));
    }
    {   // EXISTS mykey
        Boolean result = jedis.exists("mykey");
        LOGGER.info("cmd: EXISTS mykey, result: {}", result);
    }
    {   // DEL mykey
        Long result = jedis.del("mykey");
        LOGGER.info("cmd: DEL mykey, result: {}", result);
    }
    {   // GET mykey
        String result = jedis.get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result); }}Copy the code
  • JedisPool: Jedis is not thread-safe and should not be shared by multiple threadsJedisInstance, but creating a large number of Jedis can cause unnecessary overhead and even a significant impact on performance, so useJedisPoolTo avoid these problems, it is a thread-safe network connection pool. You can use it to reliably create multiple Jedis instances and recycle them back into the connection pool when you’re done.
  • JedisPool.getResourceGet a Jedis connection from the connection pool, note:JedisIt needs to be called after it is usedJedis.closeMethod to release resources.JedisTo achieve theAutoCloseable, recommended usetry-with-resourceThe written)

Lettuce

lettuce.io/

Introducing dependencies:

<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.1.7. RELEASE</version>
</dependency>
Copy the code

Lettuce is an extensible Redis client for building non-blocking Reactive applications. Built on the Netty framework, it has high performance and supports many of the advanced features of Redis. Currently springboot2.0 has the default redis client. Corresponding to the previous section, an example use of the string operation is as follows:

/** redis client */
private static final RedisClient CLIENT = RedisClient.create("redis://@test-redis-server:6379/0");

// test Binary-safe strings with Lettuce
try (StatefulRedisConnection<String, String> connection = CLIENT.connect()) {
    RedisCommands<String, String> commands = connection.sync();
    {   // SET mykey myvalue
        String result = commands.set("mykey"."myvalue");
        LOGGER.info("cmd: SET mykey myvalue, result: {}", result);
    }
    {   // GET mykey
        String result = commands.get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result);
    }
    {   // KEYS my*
        List<String> keys = commands.keys("my*");
        LOGGER.info("cmd: KEYS my*, result: {}", JsonUtils.writeValueAsString(keys, true));
    }
    {   // EXISTS mykey
        Long result = commands.exists("mykey");
        LOGGER.info("cmd: EXISTS mykey, result: {}", result);
    }
    {   // DEL mykey
        Long result = commands.del("mykey");
        LOGGER.info("cmd: DEL mykey, result: {}", result);
    }
    {   // GET mykey
        String result = commands.get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result); }}Copy the code

Spring integration

Spring-data-redis, part of the Spring Data family, provides simple configuration for easy access to Redis, low – and high-level abstractions for storage operations, and frees developers from the base implementation.

Introducing dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.1.5. RELEASE</version>
</dependency>
Copy the code

RedisTemplate is probably the most commonly used RedisTemplate when developing with Spring-data-Redis, so before we start, let’s take a look at RedisTemplate:

  • RedisTemplateRedis is a utility class that simplifies Redis access.
  • Thread-safe can be used as a singleton.
  • Its implementation revolves aroundexecuteMethod, which supports callback, which it providesRedisConnectionThe processing does not care about the declaration cycle of the connection (in short, you do not create or close the connection)

To do this, we simply define the Bean of the StringRedisTemplate in the Configuration:

/**
 * StringRedisTemplate
 * @param factory
 * @return* /
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {

    StringRedisTemplate template = new StringRedisTemplate(factory);
    StringRedisSerializer serializer = new StringRedisSerializer();	/ / (a)
    template.setKeySerializer(serializer);	/ / (2)
    template.setHashKeySerializer(serializer);
    template.setValueSerializer(serializer);
    template.setHashValueSerializer(serializer);

    return template;
}
Copy the code
  • (a) : RedisSerializer: Object serialization and deserialization to binary array interfaces, the serialization and deserialization key and the value, StringRedisSerializer, GenericJackson2JsonRedisSerializer is its implementation.

  • KeySerializer is used to serialize redis keys. HashKeySerializer is used to serialize redis hash fields. Don’t get confused.

Of course, don’t forget to add redis configuration to application.yml:

spring:
  redis:
    host: test-redis-server
    port: 6379
Copy the code

Now that we’re ready, let’s try it out. Similarly, the following is an example of the string operation:

@Resource
private StringRedisTemplate stringRedisTemplate;

/** * test Binary-safe strings with RedisTemplate */
@Test
public void testStringRedisTemplateSimple(a) {{// SET mykey myvalue
        stringRedisTemplate.opsForValue().set("mykey"."myvalue");
    }
    {   // GET mykey
        String result = stringRedisTemplate.opsForValue().get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result);
    }
    {   // KEYS my*
        Set<String> keys = stringRedisTemplate.keys("my*");
        LOGGER.info("cmd: KEYS my*, result: {}", JsonUtils.writeValueAsString(keys, true));
    }
    {   // EXISTS mykey
        Boolean result = stringRedisTemplate.hasKey("mykey");
        LOGGER.info("cmd: EXISTS mykey, result: {}", result);
    }
    {   // DEL mykey
        Boolean result = stringRedisTemplate.delete("mykey");
        LOGGER.info("cmd: DEL mykey, result: {}", result);
    }
    {   // GET mykey
        String result = stringRedisTemplate.opsForValue().get("mykey");
        LOGGER.info("cmd: GET mykey, result: {}", result); }}Copy the code
  • opsForValue: getBinary-safe stringsThe operation of the classValueOperations(That is, a wrapper class for Spring’s redis operations. Same thing, righthash,setEtc also have their corresponding encapsulationHashOperations,SetOperations, etc.).
[Copyright Notice]


This article was published on
Park Seo-kyung’s blog, allow non-commercial reprint, but reprint must retain the original author
PiaoRuiQingAnd links:
blog.piaoruiqing.comFor negotiation or cooperation on authorization, please contact:
[email protected].

The advanced

Dividing the application Cache

Caches for different applications can be divided simply by the prefix of the key

Let’s consider this question: if we want to partition the cache of different applications (services) for easy management and maintenance, how should we do this?

Perhaps adding prefixes is a good idea, but if you need to concatenate the prefix prefix into the key every time in encoding, on the one hand, it increases the workload and the risk of error on the other side, what if you forget to concatenate the prefix? The RedisSerializer interface is used to serialize and deserialize keys and values of spring-data-Redis objects. The RedisSerializer interface is used to serialize keys and values of spring-data-Redis objects.

public interface RedisSerializer<T> {
	/**
	 * Serialize the given object to binary data.
	 *
	 * @param t object to serialize. Can be {@literal null}.
	 * @return the equivalent binary data. Can be {@literal null}.
	 */
	@Nullable
	byte[] serialize(@Nullable T t) throws SerializationException;

	/**
	 * Deserialize an object from the given binary data.
	 *
	 * @param bytes object binary representation. Can be {@literal null}.
	 * @return the equivalent object instance. Can be {@literal null}.
	 */
	@Nullable
	T deserialize(@Nullable byte[] bytes) throws SerializationException;
}
Copy the code
  • serialize: object -> Byte array.
  • deserialize: Byte array -> object.

RedisTemplate’s operations on Redis are related to RedisSerializer, so you can implement this interface and specify the RedisTemplate’s KeySerializer to add the prefix. In this way, the operation of adding prefixes is removed from the business and is completely transparent and elegant to the caller, as follows:

/**
 * generic redis key serializer
 * @author piaoruiqing
 * @date: the 2019-06-11 22:37 * /
public class GenericRedisKeySerializer implements RedisSerializer<Object> {

    private final Charset charset;
    private String prefix;
    private int index;
    
    public GenericRedisKeySerializer(String prefix) {
        this(prefix, StandardCharsets.UTF_8);
    }

    public GenericRedisKeySerializer(String prefix, Charset charset) {
        Assert.notNull(charset);
        Assert.notNull(prefix);
        this.charset = charset;
        this.prefix = prefix + ":";
        index = this.prefix.length();
    }

    @Override
    public String deserialize(byte[] bytes) {
        
        if (null == bytes) {
            return null;
        }
        String key = new String(bytes, charset);
        if (key.indexOf(prefix) == 0) {
            return key.substring(index, key.length());
        }
        return key;
    }

    @Override
    public byte[] serialize(Object key) {

        if (null == key) {
            return null;
        }
        String string = key.toString();
        if(! string.startsWith(prefix)) { string = prefix + string; }returnstring.getBytes(charset); }}Copy the code

Modify the StringRedisTemplate slightly:

@Value("${spring.application.name:undefined}")
private String applicationName;
/**
 * StringRedisTemplate
 * @param factory
 * @return* /
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {

    StringRedisTemplate template = new StringRedisTemplate(factory);
// StringRedisSerializer serializer = new StringRedisSerializer();
    GenericRedisKeySerializer serializer = new GenericRedisKeySerializer(applicationName);
    template.setKeySerializer(serializer);
    template.setHashKeySerializer(serializer);
    template.setValueSerializer(serializer);
    template.setHashValueSerializer(serializer);
    return template;
}
Copy the code
  • StringRedisSerializerReplace with customGenericRedisKeySerializerSpecify the prefix as the application name

Try it out:

stringRedisTemplate.opsForValue().set("mykey"."myvalue");
String result = stringRedisTemplate.opsForValue().get("mykey");  // "myvalue"
Copy the code

Connect to Redis to view the key already prefixed

root@ubuntu:/home/ubuntu# docker exec -it redis redis-cli127.0.0.1:6379 > keys * 1)"redis-simple:mykey"
Copy the code

Custom serialization

RedisTemplate default JDK serialization JdkSerializationRedisSerializer, other ways we can be specified using serialization, such as JSON, protostuff

In the previous section, we have described how to customize the serialization method for key. The serialization configuration of value is the same as that of RedisSerializer, which is specified when creating RedisTemplate.

There are several commonly used serialization methods:

  • JDK: The default, relatively convenient, can serialize all classes, but slow and take up a large space.
  • JSON: Provides good performance and is easy to read.
  • Protostuff: High performance, fast speed and small footprint.

conclusion

This article explains the use of redis Java client, integration with Spring, and advanced use of Redis. Stay tuned for more tips on using Redis.

series

  1. Introduction to Redis
  2. Redis uses advanced levels
  3. Redis distributed lock

reference

  • redis.io
  • Spring. IO/projects/sp…
  • Github.com/xetorthio/j…
  • lettuce.io/
[Copyright Notice]


This article was published on
Park Seo-kyung’s blog, allow non-commercial reprint, but reprint must retain the original author
PiaoRuiQingAnd links:
blog.piaoruiqing.comFor negotiation or cooperation on authorization, please contact:
[email protected].