Table of Contents
1. As a cache
1.1 Why use
1.2 What kind of data is suitable to be put into the cache
1.3 Use redis as cache
1.3.1 Configuration class is not used
1.3.2 Use the configuration class
2. Distributed lock
2.1 Stress Use of testing tools
Home Java javaTutorial Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

May 09, 2023 pm 01:07 PM
java redis

1. As a cache

1.1 Why use

Data is stored in memory and data query speed is fast. Database pressure can be shared.

Analysis of Java Redis usage scenarios

1.2 What kind of data is suitable to be put into the cache

The query frequency is relatively high and the modification frequency is relatively low.

Data with low security factor

1.3 Use redis as cache

1.3.1 Configuration class is not used

Note that the entity class must be serialized:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "tb_dept")
public class Dept implements Serializable {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    private String name;
    private String realname;
}
Copy after login

Corresponding dependencies:

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--连接数据源-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mp的依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
Copy after login

Controller layer corresponding code:

@RestController
@RequestMapping("order")
public class DeptController {
    @Resource
    private DeptService deptService;
    @GetMapping("getById/{id}")
    //order/getById/1
    //{}可以放多个,由下面的传参函数对应
    //@PathVariable:获取请求映射中{}的值
    public Dept getById(@PathVariable Integer id){
        return deptService.findById(id);
    }
    @GetMapping("deleteById/{id}")
    public String deleteById(@PathVariable Integer id){
        int i = deptService.deleteById(id);
        return i>0?"删除成功":"删除失败";
    }
    @GetMapping("insert")
    public Dept insert(Dept dept){
        Dept insert = deptService.insert(dept);
        return insert;
    }
    @GetMapping("update")
    public Dept update(Dept dept){
        Dept update = deptService.update(dept);
        return update;
    }
}
Copy after login

Service layer corresponding code:

@Service
public class DeptService {
    @Resource
    private DeptMapper deptMapper;
    //当存储的value类型为对象类型使用redisTemplate
    //存储的value类型为字符串。StringRedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
    //业务代码
    public Dept findById(Integer id){
        ValueOperations forValue = redisTemplate.opsForValue();
        //查询缓存
        Object o = forValue.get("dept::" + id);
        //缓存命中
        if(o!=null){
            return (Dept) o;
        }
        Dept dept = deptMapper.selectById(id);
        if(dept!=null){
            //存入缓存中
            forValue.set("dept::"+id,dept,24, TimeUnit.HOURS);
        }
        return dept;
    }
    public int deleteById(Integer id){
        redisTemplate.delete("dept::"+id);
        int i = deptMapper.deleteById(id);
        return i;
    }
    public Dept insert(Dept dept){
        int insert = deptMapper.insert(dept);
        return dept;
    }
    public Dept update(Dept dept){
        redisTemplate.delete("dept::"+dept.getId());
        int i = deptMapper.updateById(dept);
        return dept;
    }
}
Copy after login

Configuration source:

# Configure data source
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb? serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
#sql log
mybatis-plus.configuration.log-impl=org.apache.ibatis. logging.stdout.StdOutImpl
#Connect redis
spring.redis.host=192.168.22*.1**
spring.redis.port=6379

View cache : The first part of the code is the same @before notification, and the second part of the code is also the same post notification. We can use AOP to separate caching code and business code.

The spring framework should also be able to think of it. --This can be done using annotations. Parse the annotation.

1.3.2 Use the configuration class

(1) Add the cached configuration class

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
Copy after login

(2) Use the enable cache annotation

Analysis of Java Redis usage scenarios

(3) Usage annotations

//业务代码
    //使用查询注解:cacheNames表示缓存的名称 key:唯一标志---dept::key
    //先从缓存中查看key为(cacheNames::key)是否存在,如果存在则不会执行方法体,如果不存在则执行方法体并把方法的返回值存入缓存中
    @Cacheable(cacheNames = {"dept"},key="#id")
    public Dept findById(Integer id){
        Dept dept = deptMapper.selectById(id);
        return dept;
    }
//先删除缓存在执行方法体。
    @CacheEvict(cacheNames = {"dept"},key = "#id")
    public int deleteById(Integer id){
        int row = deptMapper.deleteById(id);
        return row;
    }
    //这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。
    @CachePut(cacheNames = "dept",key="#dept.id")
    public Dept update(Dept dept){
        int insert = deptMapper.updateById(dept);
        return dept;
    }
Copy after login

2. Distributed lock

Use stress testing tools to test thread safety issues caused by high concurrency

2.1 Stress Use of testing tools

Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

##Internal configuration:

Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

Analysis of Java Redis usage scenarios

2.2 Inventory items

2.2.1 controller layer
@RestController
@RequestMapping("bucket")
public class BucketController {
    @Autowired
    private BucketService bucketService;
    @GetMapping("update/{productId}")
    public String  testUpdate(@PathVariable Integer productId){
        String s = bucketService.updateById(productId);
        return s;
    }
}
Copy after login
2.2.2 dao layer
//此处写就不需要在启动类使用注解
@Mapper
public interface BucketMapper extends BaseMapper<Bucket> {
    public Integer updateBucketById(Integer productId);
}
Copy after login
2.2.3 entity layer
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Bucket {
    @TableId(value = "productId",type = IdType.AUTO)
    private Integer productId;
    private Integer num;
}
Copy after login
2.2.4 service layer
@Service
public class BucketService {
    @Resource
    private BucketMapper bucketMapper;
    public String updateById(Integer productId){
        //查看该商品的库存数量
        Bucket bucket = bucketMapper.selectById(productId);
        if(bucket.getNum()>0){
            //修改库存每次减1
            Integer integer = bucketMapper.updateBucketById(productId);
            System.out.println("扣减成功!剩余库存数:"+(bucket.getNum()-1));
            return "success";
        }else {
            System.out.println("扣减失败!库存数不足");
            return "fail";
        }
    }
}
Copy after login
2.2.5 mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qy151wd.dao.BucketMapper">
    <update id="updateBucketById" parameterType="int">
        update bucket set num=num-1 where productId=#{productId}
    </update>
</mapper>
Copy after login
2.2.6 Dependency
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--连接数据源-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mp的依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
Copy after login
2.2.7 Test results

Analysis of Java Redis usage scenarios

We see that the same inventory is used n times. And the inventory in the database is negative. Caused by thread safety issues.

2.3 Solution

2.3.1 Use synchronized or lock lock
The corresponding service layer is modified to

@Service
public class BucketService {
    @Resource
    private BucketMapper bucketMapper;
    public String updateById(Integer productId){
        //加自动锁
        synchronized (this){
            //查看该商品的库存数量
            Bucket bucket = bucketMapper.selectById(productId);
            if(bucket.getNum()>0){
                //修改库存每次减1
                Integer integer = bucketMapper.updateBucketById(productId);
                System.out.println("扣减成功!剩余库存数:"+(bucket.getNum()-1));
                return "success";
            }else {
                System.out.println("扣减失败!库存数不足");
                return "fail";
            }
        }
    }
}
Copy after login

If a project cluster is built, then the The lock is invalid.

Analysis of Java Redis usage scenarios

2.3.2 Using redisTemplate
(1) Use idea to open a cluster project

Analysis of Java Redis usage scenarios

( 2) Use nginx

Analysis of Java Redis usage scenarios

(3) Test results

Analysis of Java Redis usage scenarios

and find that there are repeated numbers and negative inventory.

(4) Solution

Analysis of Java Redis usage scenarios

service corresponding code modification

@Service
public class BucketService {
    @Resource
    private BucketMapper bucketMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    public String updateById(Integer productId){
        ValueOperations<String,String> forValue = redisTemplate.opsForValue();
        Boolean flag = forValue.setIfAbsent("aaa::" + productId, "-----------------");
        if(flag){
            try{
                //查看该商品的库存数量
                Bucket bucket = bucketMapper.selectById(productId);
                if(bucket.getNum()>0){
                    //修改库存每次减1
                    Integer integer = bucketMapper.updateBucketById(productId);
                    System.out.println("扣减成功!剩余库存数:"+(bucket.getNum()-1));
                    return "success";
                }else {
                    System.out.println("扣减失败!库存数不足");
                    return "fail";
                }
            }finally {
                redisTemplate.delete("aaa::"+productId);
            }
        }
    return "服务器正忙,请稍后再试.......";
    }
}
Copy after login
Note that the pressure measurement speed here is not easy to be too fast (recommended 100 threads in 5 seconds)

After the pressure test, the result is:

Analysis of Java Redis usage scenarios

The above is the detailed content of Analysis of Java Redis usage scenarios. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

PHP: A Key Language for Web Development PHP: A Key Language for Web Development Apr 13, 2025 am 12:08 AM

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP vs. Python: Understanding the Differences PHP vs. Python: Understanding the Differences Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP vs. Other Languages: A Comparison PHP vs. Other Languages: A Comparison Apr 13, 2025 am 12:19 AM

PHP is suitable for web development, especially in rapid development and processing dynamic content, but is not good at data science and enterprise-level applications. Compared with Python, PHP has more advantages in web development, but is not as good as Python in the field of data science; compared with Java, PHP performs worse in enterprise-level applications, but is more flexible in web development; compared with JavaScript, PHP is more concise in back-end development, but is not as good as JavaScript in front-end development.

PHP vs. Python: Core Features and Functionality PHP vs. Python: Core Features and Functionality Apr 13, 2025 am 12:16 AM

PHP and Python each have their own advantages and are suitable for different scenarios. 1.PHP is suitable for web development and provides built-in web servers and rich function libraries. 2. Python is suitable for data science and machine learning, with concise syntax and a powerful standard library. When choosing, it should be decided based on project requirements.

How to configure Lua script execution time in centos redis How to configure Lua script execution time in centos redis Apr 14, 2025 pm 02:12 PM

On CentOS systems, you can limit the execution time of Lua scripts by modifying Redis configuration files or using Redis commands to prevent malicious scripts from consuming too much resources. Method 1: Modify the Redis configuration file and locate the Redis configuration file: The Redis configuration file is usually located in /etc/redis/redis.conf. Edit configuration file: Open the configuration file using a text editor (such as vi or nano): sudovi/etc/redis/redis.conf Set the Lua script execution time limit: Add or modify the following lines in the configuration file to set the maximum execution time of the Lua script (unit: milliseconds)

PHP: The Foundation of Many Websites PHP: The Foundation of Many Websites Apr 13, 2025 am 12:07 AM

The reasons why PHP is the preferred technology stack for many websites include its ease of use, strong community support, and widespread use. 1) Easy to learn and use, suitable for beginners. 2) Have a huge developer community and rich resources. 3) Widely used in WordPress, Drupal and other platforms. 4) Integrate tightly with web servers to simplify development deployment.

PHP vs. Python: Use Cases and Applications PHP vs. Python: Use Cases and Applications Apr 17, 2025 am 12:23 AM

PHP is suitable for web development and content management systems, and Python is suitable for data science, machine learning and automation scripts. 1.PHP performs well in building fast and scalable websites and applications and is commonly used in CMS such as WordPress. 2. Python has performed outstandingly in the fields of data science and machine learning, with rich libraries such as NumPy and TensorFlow.

PHP's Impact: Web Development and Beyond PHP's Impact: Web Development and Beyond Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

See all articles