Source code repository: github.com/zhshuixian/…

Yards cloud: gitee.com/ylooq/learn…

In the previous section, we mainly implemented Spring Boot global exception handling. In this section, we mainly content to integrate Redis for Spring Boot, which will implement the following two contents:

  • Spring Boot operates Redis directly to achieve SET and GET of K-V NoSQL
  • Spring Boot’s database cache

1. Introduction and installation of Redis

Redis is the most widely used NoSQL database on the Internet and the most widely used middleware in storage systems.

Redis is an open source (BSD-licensed), in-memory data structure server that can be used as a database, cache, message queue broker, and more. It supports many types of data structures, such as strings (), hashes (), lists (), sets (), sorted sets (). Built-in replication, Lua scripting, LRU recall, transactions, and different levels of disk persistence, as well as high availability through Redis Sentinel and automatic partitioning through Redis Cluster. “Ref. 1”

1.1 Application scenarios of Redis

After the rise of microservices and distributed, Redis has been widely applied in Internet companies with more and more application scenarios:

  • Cache: This is the most used area of Redis, Redis will directly store all data in memory, its access speed is much faster than MySQL and other databases need to query from the hard disk, if the SQL data is written to the cache, can greatly improve the performance of the system, reduce the pressure on the database. Redis cache can also be used to share data across processes.
  • Persistence: for example: For each microservice component, the built-in Session mechanism cannot be shared across processes. If a Session is written into Redis, it can realize Session sharing among different microservice processes and persist the Session to the hard disk through Redis. This prevents server Session loss caused by server downtime and restart.
  • Distributed lock: For data shared between processes, it is necessary to avoid the generation of dirty data by locking. You can use Redis single thread feature to lock and release shared data.
  • Publish, subscribe: Yes, Redis can be used as a lightweight message queue;
  • More: limits on interface access, behavior history of cache users, content likes, leaderboards, etc

1.2. Installation of Redis

Linux is used here. For Windows platforms, you can use WSL or install a Linux distribution on a virtual machine.

Install the software required for the compilation
sudo apt install gcc g++ make
Copy the code

IO/Download

# download RedisWget http://download.redis.io/releases/redis-5.0.8.tar.gz tar XVF - redis - 5.0.8. Tar. GzcdRedis - 5.0.8# compiler
mark
Copy the code

Simple configuration of Redis: vim redis.conf

# add, Redis password, default is empty
requirepass springboot
Comment out bind to allow remote access, or add a space to separate the IP from which to run remote access
# bind 127.0.0.1
The protected mode is disabled and IP access is allowed
protected-mode no
Copy the code

Redis start

The background runs as a service
src/redis-server redis.conf --daemonize yes
The default port number is 6379
src/redis-cli -p 6379 -a springboot
 Key = name,value = springboot127.0.0.1:6379 >setName springboot OK 127.0.0.1:6379> get name"springboot"127.0.0.1:6379 > del name (integer) 1
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379>exit
# Stop Redis service and save data to hard disk
./src/redis-cli -p 6379 -a springboot  shutdown save
Copy the code

2. Start using Redis

Create a new project 10-spring-boot-redis and add the following dependencies:

// Gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.11.'
MyBatis = MyBatis = MyBatis = MyBatis = MyBatis = MyBatis = MyBatis = MyBatis = MyBatis
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'mysql:mysql-connector-java'
Copy the code

File application. Properties configuration Redis connection, MySQL connection, MyBatis, JPA

# Redis host ip
spring.redis.host=wsl
# Redis server connection port
spring.redis.port=6379
# Redis database index (default 0)
spring.redis.database=0
# Redis server connection password (default null)
spring.redis.password=springboot
# maximum number of connections in the pool (use negative values to indicate no limit)
spring.redis.jedis.pool.max-active=8
Maximum connection pool blocking wait time (negative value indicates no limit)
spring.redis.jedis.pool.max-wait=-1
The maximum number of free connections in the connection pool
spring.redis.jedis.pool.max-idle=8
Minimum free connection in connection pool
spring.redis.jedis.pool.min-idle=0
Connection timeout (ms)
spring.redis.timeout=500
# Use Redis cache
spring.cache.type=redis

You only need to change the database URL, username, password, and JDBC Driver
MySQL 8 needs to specify serverTimezone to connect to MySQLspring.datasource.url=jdbc:mysql://localhost:3306/spring? useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.password=xiaoxian
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Some configuration of Hibernate
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
Whether to display SQL execution statements in Log
spring.jpa.show-sql=true
# hibernate.ddl-auto configures operations on database tables
spring.jpa.hibernate.ddl-auto=none

# MyBatis Hump naming conversion
mybatis.configuration.map-underscore-to-camel-case=true
# display Mybatis SQL, Mapper package print debug level code
logging.level.org.xian.redis.repository=debug
Copy the code

Start the redisApplication.java class to configure MyBatis mapper and enable cache configuration.

@SpringBootApplication
@EnableCaching
@MapperScan("org.xian.redis.repository")
public class RedisApplication.Copy the code

2.1 Configuration of Redis

New RedisConfig. Java

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
    @Bean
    public RedisCacheConfiguration cacheConfiguration(a) {
        // Set the cache expiration time to 120 seconds
        return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(120)).disableCachingNullValues();
    }
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        // Use RedisCacheManager as the cache manager
        return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration()).transactionAware().build();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // Jackson sequence mode
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // Jackson automatically recognizes Public modified member variables, getters, and setters by default
        // Private, protected, and public member variables can be automatically identified without specifying getters, setters, or public.
        / / reference https://blog.csdn.net/sdyy321/article/details/40298081
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // For the eight basic data types and their enclosing classes and strings, the other types are serialized with that type and value
        / / reference https://www.jianshu.com/p/c5fcd2a1ab49
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        / / Redis links
        template.setConnectionFactory(redisConnectionFactory);
        // Redis key-value serializes using Jackson
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // Redis hashkey-hashValue serialization uses Jackson
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        returntemplate; }}Copy the code

The default RedisTemplate is RedisTemplate<Object, Object>, that is, Key and Value are both generic, and the Key is defined as a String.

Use Jackson as serialization tool, because of its default JdkSerializationRedisSerializer, its serialized as binary data into Redis, unfavorable to view the original content. Using JSON as a serialization tool, other programming languages can also be easily accessed.

2.2、Redis 的 get 和 set

Here we demonstrate storing and reading Redis data using RedisTemplate and StringRedisTemplate.

@RestController
@CacheConfig(cacheNames = "users")
public class RedisController {
    @Resource StringRedisTemplate stringTemplate;
    @Resource RedisTemplate<String, User> redisTemplate;

    @RequestMapping("/setString")
    public String setString(@RequestParam(value = "key") String key,
                            @RequestParam(value = "value") String value) {
        stringTemplate.opsForValue().set(key, value);
        return "ok";
    }
    
    @RequestMapping("/getString")
    public String getString(@RequestParam(value = "key") String key) {
        return stringTemplate.opsForValue().get(key);
    }
    // User classes set, get, and time limits
    @RequestMapping(value = "/setUser")
    public String setUser(@RequestBody User user) {
        // It will expire after 1 minute
        redisTemplate.opsForValue().set(user.getUsername(), user, Duration.ofMinutes(1));
        return "ok";
    }
    
    @RequestMapping("/getUser")
    public User getUser(@RequestParam(value = "key") String key) {
        return redisTemplate.opsForValue().get(key);
    }
    
    @RequestMapping("/delUser")
    public User delUser(@RequestParam(value = "key") String key) {
        User user = redisTemplate.opsForValue().get(key);
        / / delete
        redisTemplate.delete(key);
        returnuser; }}Copy the code

Set (key, value,time_out), you can specify the expiration time of Redis by the third parameter.

Run the project, access the above urls separately, and test their effect.

2.2. Database cache

Java file, SQL script in user. SQL, not written here insert Controller, and omit the service layer.

@Entity
@Table(name = "user", schema = "spring")
public class User implements Serializable {
    private static final long serialVersionUID = 413797298970501130L;
    @Id private String username;
    private Byte age;
    // Omit the Getter setter
}
Copy the code

File UserMapper:

package org.xian.redis.repository;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.xian.redis.entity.User;

public interface UserMapper {
    @Select("Select username, age From user Where username=#{username}")
    User selectByUsername(String username);
    
    @Update("Update user Set age=#{age} Where username=#{username}")
    void update(User user);

    @Delete("Delete From user where username=#{username}")
    void delete(String username);
}
Copy the code

Add the following to RedisController

@RequestMapping("/deleteAllCache")
@CacheEvict(allEntries = true)
public String deleteAllCache(a) {
    // Delete all caches
    return "OK";
}

@RequestMapping("/mySelect")
@Cacheable(key = "#username")
public User mySelect(@RequestParam(value = "username") String username) {
    return userMapper.selectByUsername(username);
}

@RequestMapping("/myUpdate")
@CachePut(key = "#user.username")
public User myUpdate(@RequestBody User user) {
    userMapper.update(user);
    return userMapper.selectByUsername(user.getUsername());
}

@RequestMapping("/myDelete")
@CacheEvict(key = "#username")
public User myDelete(@RequestParam(value = "username") String username) {
    userMapper.delete(username);
    return userMapper.selectByUsername(username);
}
Copy the code

Code parsing: Three annotations commonly used for caching.

@cacheable (key = “#username”) writes the result to the Redis cache. If the key value already exists in the cache, the system returns the key value directly instead of executing the SQL query. The SQL query is executed only when there is no data in the cache. That is to see whether the cache, there is a direct return, no query database.

@cacheput (key = “#user.username”), similar to @cacheable, operates on myUpdate() and is not written to or updated until after execution.

@cacheevict (key = “#username”) deletes the contents of the cache based on the key. If allEntries = true is specified all caches under @Cacheconfig (cacheNames = “Users “) will be deleted.

Run the project, go to /mySelect? Username =boot, the terminal will print SQL statements, query SQL, access within the cache validity period, and directly return the cache content. They don’t look it up in the database.

Access /select within cache life? Username =boot, a JPA API interface, also does not query database. Interested partners can try, the relevant code has been uploaded to the GitHub repository.

The other interfaces are not listed here.

Note: @cache * is not used in a Repository or Mapper interface, but in a specific way. For example, at the Service interface or Controller interface layer.

In addition, the cache can specify keyGenerator to automatically generate a Key value, which is not implemented here, but manually specified by Key = “#username”.

Reference 1 is recommended for more Redis operation apis, such as arrays, collections, and Hash

Reference 1: Learn about Redis and use Redis “www.ibm.com/developerwo…” in Spring Boot projects

The next section covers Spring Boot integration with MangoDB (another popular NoSQL) or a brief introduction to Redis distributed locking. More content can pay attention to xiaoxian CSDN blog “big Data Xiaoxian” or the public number “Advanced programming technology” oh.