Spring Boot 2.x: Integrating Redis, this is enough

Posted by svgk01 on Fri, 09 Aug 2019 03:15:50 +0200

[TOC]

Introduction to Redis

Redis is an open source, non-relational database (NoSQL) written in ANSI C, compliant with the BSD protocol, network support, memory-based and persistent log, Key-Value database, and multilingual API s.

Features of Redis

  1. All operations of Redis are atomic, meaning they either succeed or fail completely.A single operation is atomic.Multiple operations also support transactions, that is, atomicity, wrapped up in MULTI and EXEC directives.
  2. Very high performance - Redis reads 110,000 times per second and writes 81,000 times per second.Rich Data Types - Redis supports Strings, Lists, Hashes, Sets, and Ordered Sets data type operations for binary cases.
  3. Atomic - All operations of Redis are atomic, meaning they either succeed or fail without execution at all.A single operation is atomic.Multiple operations also support transactions, that is, atomicity, wrapped up in MULTI and EXEC directives.
  4. Rich features - Redis also supports publish/subscribe, notification, key expiration, and so on.

Application of Redis

  1. Session Cache
  2. Data Cache
  3. Charts/Counters
  4. Message Queue

Redis data type

  • String:String
  • Hash:Hash
  • List:List
  • Set:Set
  • Sorted Set: Ordered Set

Deployment of Redis

PS: I'm here based on the Mac environment, where students can install Linux virtual machine synchronization to operate.

  1. Official Download Stable version

  1. Find the downloaded file, unzip and compile it
tar -zxvf redis-5.0.4.tar.gz
mv redis-5.0.4 /usr/local/
cd /usr/local/redis-5.0.4/
make test

To do this, it's best to run make test once to make sure the compilation passes, which takes about three minutes.
At this point, the test has passed.Let's go on

make
cd src/
make install

Now that we've finished installing here, let's do some redis configuration:

vim ../redis.conf

Find about 136 rows of daemonize and change its property to yes to allow redis to run in the background, and then find about 500 rows of requirepass, followed by the password we need to set, so we can access redis with the password.
Then we start redis by specifying a configuration file

./redis-server ../redis.conf

When you're done, check to see if the execution was successful:

ps -ef | grep redis

As you can see, our redis have started successfully, and then we can access them through rdm:

Successfully accomplished, now everything is ready, only the East wind.Let's take a look at how redis can be used in Spring Boot.

Use in Spring Boot

Spring Boot provides us with ready-made spring-boot-starter-data-redis, which we only need to import into the pom file.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- Create connection pool -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

Then we need to configure some information about redis in the configuration file:

spring:
  redis:
    host: 127.0.0.1  # IP
    port: 6379  # Port number
    password: 123456  # Password
    lettuce:
      pool:
        max-active: 8 # Maximum Connections in Connection Pool
        max-wait: -1ms  # Maximum blocking wait time for connection pool (use a negative value to indicate no limit)
        min-idle: 0 # Minimum idle connection in connection pool
        max-idle: 8 # Maximum idle connection in connection pool

Next, we need to encapsulate the Redis operation we need into an interface so that we can call it. Here I implement a Redis method based on the interface, Abstract class, and implement the structure of the class. The required classmates can download it from GitHub (subproject name: viboot-rds), and GitHub's address is at the end.Only some methods of the interface are pasted here.

package com.itframe.dao;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 */
public interface RedisDao {

    /**
     * Determine if there is a corresponding value in the cache
     * 
     * @param key
     * @return boolean
     */
    public boolean existsKey(Object key);

    /**
     * Get a list of keys based on the key (the key value can be a fuzzy match - - taskInfo:taskDetail:* <---> * for any character)
     * 
     * @param pattern
     * @return Set<Object>
     */
    public Set<Object> keys(Object pattern);

    /**
     * Delete the corresponding value according to the key
     * 
     * @param key
     */
    public boolean delete(Object key);

    /**
     * Get Number by key
     * 
     * @param key
     */
    public int count(Object key);

    /**
     * Bulk Delete Corresponding value
     * 
     * @param keys
     */
    public void delete(String[] keys);

    /**
     * Bulk delete key(key value can be a fuzzy match - - taskInfo:taskDetail:* <---> * for any character)
     * 
     * @param pattern
     */
    public long deletePattern(Object pattern);

    /**
     * Bulk Delete Corresponding value
     * 
     * @param keys
     */
    public long delete(Set<Object> keys);

    /**
     * Write Cache (Action String)
     * 
     * @param key
     * @param value
     * @return boolean
     */
    public boolean vSet(Object key, Object value);

    /**
     * Write Cache Set Aging Time (Action String)
     * 
     * @param key
     * @param value
     * @return boolean
     */
    public boolean vSet(Object key, Object value, Long expireTime);

    /**
     * Update Write Cache Settings Aging Time (Action String)
     * 
     * @param key
     * @return boolean
     */
    public boolean vSetUpdate(Object key, Long expireTime);

    /**
     * Read Cache (Action String)
     * 
     * @param key
     * @return Object
     */
    public Object vGet(Object key);

    /**
     * Hash Add (operation hash)
     * 
     * @param key
     * @param hashKey
     * @param value
     */
    public void hmSet(Object key, Object hashKey, Object value);

    /**
     * Hash Add (operation hash)
     * 
     * @param key
     * @param map
     */
    public void hmSetAll(Object key, Map<Object, Object> map);

    /**
     * Hash Get Data (operation hash)
     * 
     * @param key
     * @return Map<Object, Object>
     */
    public Map<Object, Object> hmGet(Object key);

    /**
     * Hash Get Data (operation hash)
     * 
     * @param key
     * @param hashKey
     * @return Object
     */
    public Object hmGet(Object key, Object hashKey);

    /**
     * Hash Delete Data (operation hash)
     * 
     * @param key
     * @param hashKey
     * @return Object
     */
    public Object hmDel(Object key, Object hashKey);

}

In the abstract class we initialized and serialized RedisTemplate:

public abstract class AbstractBaseRedisDao<K, V> {

    @Resource(name = "redisTemplate")
    protected RedisTemplate<K, V> redisTemplate;

    /**
     * Set redisTemplate
     * 
     * @param redisTemplate
     */
    public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * Get RedisSerializer
     */
    protected RedisSerializer<String> getRedisSerializer() {
        return redisTemplate.getStringSerializer();
    }
}

In the implementation class we implement methods in the interface by manipulating RestTemplate~

Redis Cache Actual

First, if you want to enable caching in the SpringBoot project, you need to add the comment @EnableCaching to the startup class. This is the key point, remember!

Start with the commentary Three Swordsmen: @Cacheable, @CachePut, @CacheEvict.

  • @Cacheable: A method configuration that caches methods based on their request parameters, often used for query operations
  • @CachePut: A method configuration that caches methods based on their request parameters and is often used for modification operations
  • @CacheEvict: Empty the cache, mainly for delete operations.

Let's look at the usage below:


    /**
     *    value: Name of the cache
     *    key: Cached keys
     *    return Cached value
     */ 
    @Override
    @Cacheable(value = "users", key = "#id")
    public UserDO findOne(Long id) {
        // If we visit it for the second time, the console does not print out this statement that it was taken out of the cache
        log.info("From MYSQL");
        return userMapper.get(id);
    }

    @Override
    @CachePut(value = "users", key = "#userDO.id")
    public UserDO update(UserDO userDO) {
        // After execution, when you visit findOne again, you should not print out "From MySQL", and the value we modified is returned, indicating that this step was cached successfully
        if (userMapper.update(userDO) > 0) {
            return userMapper.get(userDO.getId());
        }
        return null;
    }

    @Override
    @CacheEvict(value = "users", key = "#id")
    public int delete(Long id) {
        // View in rdm after execution
        return userMapper.delete(id);
    }

Test 1

First visit to findOne

Second visit to findOne:

It's still just the result, but the console didn't print anything indicating that the cache was successful

Test 2

Call findOne again after calling update:

You can see that the information has been modified and the database has not been accessed

Test 3

Visit delete to see rdm:

Explain deletion succeeded~

Source Address

Github
Gitee

Remember to hit the star, you must be the greatest motivation for me to write!

Public Number

The original article, limited in writing, is light in learning. If there are any errors in the article, we hope to inform you

Topics: Java Redis Spring Database