Spring Boot 项目中 Redis 与数据库性能对比实战:从缓存配置到时间分析, ...

金歌  金牌会员 | 2024-10-23 05:09:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 860|帖子 860|积分 2580

一、媒介:

    在现代应用中,随着数据量的增大和访问频率的提高,怎样提高数据存取的性能变得尤为告急。缓存技能作为一种常见的优化本领,被广泛应用于减少数据库访问压力、提拔体系响应速度。Redis 作为一种高效的内存缓存数据库,因其卓越的性能和丰富的数据范例支持,在开发中占据了告急位置。
    本篇文章将详细先容怎样在 Spring Boot 项目中使用 Redis,创建简朴的缓存机制,并实现数据存取的时间比力。通过这个实战项目,你将学习怎样在 Redis 和 MySQL 之间存取数据,并丈量两者的性能差异,从而对缓存策略有更加深入的明确。
二、详细利用:

2.1、环境预备和项目布局

起首,你需要预备一个 Spring Boot 项目,并确保项目布局中包含以下依赖:


  • Spring Web:用于构建 RESTful API
  • MyBatis:数据库利用框架
  • Spring Data Redis:用于 Redis 利用
  • MySQL Driver:用于与 MySQL 数据库交互
  1. <dependencies>
  2.         <dependency>
  3.             <groupId>org.springframework.boot</groupId>
  4.             <artifactId>spring-boot-starter-web</artifactId>
  5.         </dependency>
  6.         <dependency>
  7.             <groupId>com.mysql</groupId>
  8.             <artifactId>mysql-connector-j</artifactId>
  9.             <scope>runtime</scope>
  10.         </dependency>
  11.         <dependency>
  12.             <groupId>org.springframework.boot</groupId>
  13.             <artifactId>spring-boot-starter-test</artifactId>
  14.             <scope>test</scope>
  15.         </dependency>
  16.         <!-- MyBatis Starter -->
  17.         <dependency>
  18.             <groupId>org.mybatis.spring.boot</groupId>
  19.             <artifactId>mybatis-spring-boot-starter</artifactId>
  20.             <version>3.0.0</version>
  21.         </dependency>
  22.         <!-- Spring Boot Redis Starter -->
  23.         <dependency>
  24.             <groupId>org.springframework.boot</groupId>
  25.             <artifactId>spring-boot-starter-data-redis</artifactId>
  26.         </dependency>
  27.         
  28.         <dependency>
  29.             <groupId>org.projectlombok</groupId>
  30.             <artifactId>lombok</artifactId>
  31.             <version>1.18.30</version>
  32.         </dependency>
  33.     </dependencies>
复制代码
同时项目布局如下,是一个非常普通的SpringBoot项目

同时还要在application.properties中配置好对应的MySQL和MyBatis信息:
  1. spring.datasource.url=jdbc:mysql://localhost:3306/yourDatabase
  2. spring.datasource.username=root
  3. spring.datasource.password=root
  4. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  5. mybatis.mapper-locations=classpath:mapper/*.xml
复制代码
2.2、创建实体类

实体类 User 用于表示用户的基本信息,包含 id 和 name 两个字段。代码如下:
  1. @Data
  2. public class User {
  3.     private Long id;
  4.     private String name;
  5. }
复制代码
2.3、配置MyBatis Mapper层

创建一个接口 UserMapper 来利用数据库,并通过 MyBatis 的 XML 文件实现具体的 SQL 利用:
  1. @Mapper
  2. public interface UserMapper {
  3.     User selectUserById(Long id);
  4. }
复制代码
  1. <mapper namespace="com.example.redis.mapper.UserMapper">
  2.     <select id="selectUserById" resultType="com.example.redis.entity.User">
  3.         SELECT id, name FROM user WHERE id = #{id}
  4.     </select>
  5. </mapper>
复制代码
2.4、Redis配置与工具类

自界说的 Redis 配置类 RedisConfig,它基于 Jackson 的 JSON 序列化器进行 Redis 数据存储与读取,确保数据可以以对象形式生存到 Redis 中。(这个配置类和工具类是在网上找的)配置如下:
  1. @Configuration
  2. public class RedisConfig {
  3.     // 自己定义了一个RedisTemplate
  4.     @Bean
  5.     @SuppressWarnings("all")
  6.     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  7.         // 我们为了自己开发方便,一般直接使用 <String, Object>
  8.         RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
  9.         template.setConnectionFactory(factory);
  10.         // Json序列化配置
  11.         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  12.         ObjectMapper om = new ObjectMapper();
  13.         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  14.         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  15.         jackson2JsonRedisSerializer.setObjectMapper(om);
  16.         // String 的序列化
  17.         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  18.         // key采用String的序列化方式
  19.         template.setKeySerializer(stringRedisSerializer);
  20.         // hash的key也采用String的序列化方式
  21.         template.setHashKeySerializer(stringRedisSerializer);
  22.         // value序列化方式采用jackson
  23.         template.setValueSerializer(jackson2JsonRedisSerializer);
  24.         // hash的value序列化方式采用jackson
  25.         template.setHashValueSerializer(jackson2JsonRedisSerializer);
  26.         template.afterPropertiesSet();
  27.         return template;
  28.     }
  29. }
复制代码
工具类 RedisUtil 提供了简朴的 Redis 利用方法,例如设置键值对、获取缓存、检查键是否存在等:
  1. package com.example.redis.utils;
  2. import jakarta.annotation.Resource;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.util.CollectionUtils;
  7. import java.util.Collection;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import java.util.concurrent.TimeUnit;
  12. @Component
  13. public final class RedisUtil {
  14.     @Autowired
  15.     private RedisTemplate<String, Object> redisTemplate;
  16.     public Set<String> keys(String keys){
  17.         try {
  18.             return redisTemplate.keys(keys);
  19.         }catch (Exception e){
  20.             e.printStackTrace();
  21.             return null;
  22.         }
  23.     }
  24.     /**
  25.      * 指定缓存失效时间
  26.      * @param key 键
  27.      * @param time 时间(秒)
  28.      * @return
  29.      */
  30.     public boolean expire(String key, long time) {
  31.         try {
  32.             if (time > 0) {
  33.                 redisTemplate.expire(key, time, TimeUnit.SECONDS);
  34.             }
  35.             return true;
  36.         } catch (Exception e) {
  37.             e.printStackTrace();
  38.             return false;
  39.         }
  40.     }
  41.     /**
  42.      * 根据key 获取过期时间
  43.      * @param key 键 不能为null
  44.      * @return 时间(秒) 返回0代表为永久有效
  45.      */
  46.     public long getExpire(String key) {
  47.         return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  48.     }
  49.     /**
  50.      * 判断key是否存在
  51.      * @param key 键
  52.      * @return true 存在 false不存在
  53.      */
  54.     public boolean hasKey(String key) {
  55.         try {
  56.             return redisTemplate.hasKey(key);
  57.         } catch (Exception e) {
  58.             e.printStackTrace();
  59.             return false;
  60.         }
  61.     }
  62.     /**
  63.      * 删除缓存
  64.      * @param key 可以传一个值 或多个
  65.      */
  66.     @SuppressWarnings("unchecked")
  67.     public void del(String... key) {
  68.         if (key != null && key.length > 0) {
  69.             if (key.length == 1) {
  70.                 redisTemplate.delete(key[0]);
  71.             } else {
  72.                 redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
  73.             }
  74.         }
  75.     }
  76.     /**
  77.      * 普通缓存获取
  78.      * @param key 键
  79.      * @return 值
  80.      */
  81.     public Object get(String key) {
  82.         return key == null ? null : redisTemplate.opsForValue().get(key);
  83.     }
  84.     /**
  85.      * 普通缓存放入
  86.      * @param key 键
  87.      * @param value 值
  88.      * @return true成功 false失败
  89.      */
  90.     public boolean set(String key, Object value) {
  91.         try {
  92.             redisTemplate.opsForValue().set(key, value);
  93.             return true;
  94.         } catch (Exception e) {
  95.             e.printStackTrace();
  96.             return false;
  97.         }
  98.     }
  99.      /**
  100.      * 普通缓存放入, 不存在放入,存在返回
  101.      * @param key 键
  102.      * @param value 值
  103.      * @return true成功 false失败
  104.      */
  105.     public boolean setnx(String key, Object value) {
  106.         try {
  107.             redisTemplate.opsForValue().setIfAbsent(key,value);
  108.             return true;
  109.         } catch (Exception e) {
  110.             e.printStackTrace();
  111.             return false;
  112.         }
  113.     }
  114.     /**
  115.      * 普通缓存放入并设置时间
  116.      * @param key 键
  117.      * @param value 值
  118.      * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  119.      * @return true成功 false 失败
  120.      */
  121.     public boolean set(String key, Object value, long time) {
  122.         try {
  123.             if (time > 0) {
  124.                 redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  125.             } else {
  126.                 set(key, value);
  127.             }
  128.             return true;
  129.         } catch (Exception e) {
  130.             e.printStackTrace();
  131.             return false;
  132.         }
  133.     }
  134.   /**
  135.      * 普通缓存放入并设置时间,不存在放入,存在返回
  136.      * @param key 键
  137.      * @param value 值
  138.      * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  139.      * @return true成功 false 失败
  140.      */
  141.     public boolean setnx(String key, Object value, long time) {
  142.         try {
  143.             if (time > 0) {
  144.                 redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
  145.             } else {
  146.                 set(key, value);
  147.             }
  148.             return true;
  149.         } catch (Exception e) {
  150.             e.printStackTrace();
  151.             return false;
  152.         }
  153.     }
  154.     /**
  155.      * 递增
  156.      * @param key 键
  157.      * @param delta 要增加几(大于0)
  158.      * @return
  159.      */
  160.     public long incr(String key, long delta) {
  161.         if (delta < 0) {
  162.             throw new RuntimeException("递增因子必须大于0");
  163.         }
  164.         return redisTemplate.opsForValue().increment(key, delta);
  165.     }
  166.     /**
  167.      * 递减
  168.      * @param key 键
  169.      * @param delta 要减少几(小于0)
  170.      * @return
  171.      */
  172.     public long decr(String key, long delta) {
  173.         if (delta < 0) {
  174.             throw new RuntimeException("递减因子必须大于0");
  175.         }
  176.         return redisTemplate.opsForValue().increment(key, -delta);
  177.     }
  178.     /**
  179.      * HashGet
  180.      * @param key 键 不能为null
  181.      * @param item 项 不能为null
  182.      * @return 值
  183.      */
  184.     public Object hget(String key, String item) {
  185.         return redisTemplate.opsForHash().get(key, item);
  186.     }
  187.     /**
  188.      * 获取hashKey对应的所有键值
  189.      * @param key 键
  190.      * @return 对应的多个键值
  191.      */
  192.     public Map<Object, Object> hmget(String key) {
  193.         return redisTemplate.opsForHash().entries(key);
  194.     }
  195.     /**
  196.      * HashSet
  197.      * @param key 键
  198.      * @param map 对应多个键值
  199.      * @return true 成功 false 失败
  200.      */
  201.     public boolean hmset(String key, Map<String, Object> map) {
  202.         try {
  203.             redisTemplate.opsForHash().putAll(key, map);
  204.             return true;
  205.         } catch (Exception e) {
  206.             e.printStackTrace();
  207.             return false;
  208.         }
  209.     }
  210.     /**
  211.      * HashSet 并设置时间
  212.      * @param key 键
  213.      * @param map 对应多个键值
  214.      * @param time 时间(秒)
  215.      * @return true成功 false失败
  216.      */
  217.     public boolean hmset(String key, Map<String, Object> map, long time) {
  218.         try {
  219.             redisTemplate.opsForHash().putAll(key, map);
  220.             if (time > 0) {
  221.                 expire(key, time);
  222.             }
  223.             return true;
  224.         } catch (Exception e) {
  225.             e.printStackTrace();
  226.             return false;
  227.         }
  228.     }
  229.     /**
  230.      * 向一张hash表中放入数据,如果不存在将创建
  231.      * @param key 键
  232.      * @param item 项
  233.      * @param value 值
  234.      * @return true 成功 false失败
  235.      */
  236.     public boolean hset(String key, String item, Object value) {
  237.         try {
  238.             redisTemplate.opsForHash().put(key, item, value);
  239.             return true;
  240.         } catch (Exception e) {
  241.             e.printStackTrace();
  242.             return false;
  243.         }
  244.     }
  245.     /**
  246.      * 向一张hash表中放入数据,如果不存在将创建
  247.      * @param key 键
  248.      * @param item 项
  249.      * @param value 值
  250.      * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  251.      * @return true 成功 false失败
  252.      */
  253.     public boolean hset(String key, String item, Object value, long time) {
  254.         try {
  255.             redisTemplate.opsForHash().put(key, item, value);
  256.             if (time > 0) {
  257.                 expire(key, time);
  258.             }
  259.             return true;
  260.         } catch (Exception e) {
  261.             e.printStackTrace();
  262.             return false;
  263.         }
  264.     }
  265.     /**
  266.      * 删除hash表中的值
  267.      * @param key 键 不能为null
  268.      * @param item 项 可以使多个 不能为null
  269.      */
  270.     public void hdel(String key, Object... item) {
  271.         redisTemplate.opsForHash().delete(key, item);
  272.     }
  273.     /**
  274.      * 判断hash表中是否有该项的值
  275.      * @param key 键 不能为null
  276.      * @param item 项 不能为null
  277.      * @return true 存在 false不存在
  278.      */
  279.     public boolean hHasKey(String key, String item) {
  280.         return redisTemplate.opsForHash().hasKey(key, item);
  281.     }
  282.     /**
  283.      * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  284.      * @param key 键
  285.      * @param item 项
  286.      * @param by 要增加几(大于0)
  287.      * @return
  288.      */
  289.     public double hincr(String key, String item, double by) {
  290.         return redisTemplate.opsForHash().increment(key, item, by);
  291.     }
  292.     /**
  293.      * hash递减
  294.      * @param key 键
  295.      * @param item 项
  296.      * @param by 要减少记(小于0)
  297.      * @return
  298.      */
  299.     public double hdecr(String key, String item, double by) {
  300.         return redisTemplate.opsForHash().increment(key, item, -by);
  301.     }
  302.     /**
  303.      * 根据key获取Set中的所有值
  304.      * @param key 键
  305.      * @return
  306.      */
  307.     public Set<Object> sGet(String key) {
  308.         try {
  309.             return redisTemplate.opsForSet().members(key);
  310.         } catch (Exception e) {
  311.             e.printStackTrace();
  312.             return null;
  313.         }
  314.     }
  315.     /**
  316.      * 根据value从一个set中查询,是否存在
  317.      * @param key 键
  318.      * @param value 值
  319.      * @return true 存在 false不存在
  320.      */
  321.     public boolean sHasKey(String key, Object value) {
  322.         try {
  323.             return redisTemplate.opsForSet().isMember(key, value);
  324.         } catch (Exception e) {
  325.             e.printStackTrace();
  326.             return false;
  327.         }
  328.     }
  329.     /**
  330.      * 将数据放入set缓存
  331.      * @param key 键
  332.      * @param values 值 可以是多个
  333.      * @return 成功个数
  334.      */
  335.     public long sSet(String key, Object... values) {
  336.         try {
  337.             return redisTemplate.opsForSet().add(key, values);
  338.         } catch (Exception e) {
  339.             e.printStackTrace();
  340.             return 0;
  341.         }
  342.     }
  343.     /**
  344.      * 将set数据放入缓存
  345.      * @param key 键
  346.      * @param time 时间(秒)
  347.      * @param values 值 可以是多个
  348.      * @return 成功个数
  349.      */
  350.     public long sSetAndTime(String key, long time, Object... values) {
  351.         try {
  352.             Long count = redisTemplate.opsForSet().add(key, values);
  353.             if (time > 0){
  354.                 expire(key, time);
  355.             }
  356.             return count;
  357.         } catch (Exception e) {
  358.             e.printStackTrace();
  359.             return 0;
  360.         }
  361.     }
  362.     /**
  363.      * 获取set缓存的长度
  364.      * @param key 键
  365.      * @return
  366.      */
  367.     public long sGetSetSize(String key) {
  368.         try {
  369.             return redisTemplate.opsForSet().size(key);
  370.         } catch (Exception e) {
  371.             e.printStackTrace();
  372.             return 0;
  373.         }
  374.     }
  375.     /**
  376.      * 移除值为value的
  377.      * @param key 键
  378.      * @param values 值 可以是多个
  379.      * @return 移除的个数
  380.      */
  381.     public long setRemove(String key, Object... values) {
  382.         try {
  383.             Long count = redisTemplate.opsForSet().remove(key, values);
  384.             return count;
  385.         } catch (Exception e) {
  386.             e.printStackTrace();
  387.             return 0;
  388.         }
  389.     }
  390.     // ===============================list=================================
  391.     /**
  392.      * 获取list缓存的内容
  393.      * @param key 键
  394.      * @param start 开始
  395.      * @param end 结束 0 到 -1代表所有值
  396.      * @return
  397.      */
  398.     public List<Object> lGet(String key, long start, long end) {
  399.         try {
  400.             return redisTemplate.opsForList().range(key, start, end);
  401.         } catch (Exception e) {
  402.             e.printStackTrace();
  403.             return null;
  404.         }
  405.     }
  406.     /**
  407.      * 获取list缓存的长度
  408.      * @param key 键
  409.      * @return
  410.      */
  411.     public long lGetListSize(String key) {
  412.         try {
  413.             return redisTemplate.opsForList().size(key);
  414.         } catch (Exception e) {
  415.             e.printStackTrace();
  416.             return 0;
  417.         }
  418.     }
  419.     /**
  420.      * 通过索引 获取list中的值
  421.      * @param key 键
  422.      * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  423.      * @return
  424.      */
  425.     public Object lGetIndex(String key, long index) {
  426.         try {
  427.             return redisTemplate.opsForList().index(key, index);
  428.         } catch (Exception e) {
  429.             e.printStackTrace();
  430.             return null;
  431.         }
  432.     }
  433.     /**
  434.      * 将list放入缓存
  435.      * @param key 键
  436.      * @param value 值
  437.      * @return
  438.      */
  439.     public boolean lSet(String key, Object value) {
  440.         try {
  441.             redisTemplate.opsForList().rightPush(key, value);
  442.             return true;
  443.         } catch (Exception e) {
  444.             e.printStackTrace();
  445.             return false;
  446.         }
  447.     }
  448.     /**
  449.      * 将list放入缓存
  450.      * @param key 键
  451.      * @param value 值
  452.      * @param time 时间(秒)
  453.      * @return
  454.      */
  455.     public boolean lSet(String key, Object value, long time) {
  456.         try {
  457.             redisTemplate.opsForList().rightPush(key, value);
  458.             if (time > 0){
  459.                 expire(key, time);
  460.             }
  461.             return true;
  462.         } catch (Exception e) {
  463.             e.printStackTrace();
  464.             return false;
  465.         }
  466.     }
  467.     /**
  468.      * 将list放入缓存
  469.      * @param key 键
  470.      * @param value 值
  471.      * @return
  472.      */
  473.     public boolean lSet(String key, List<Object> value) {
  474.         try {
  475.             redisTemplate.opsForList().rightPushAll(key, value);
  476.             return true;
  477.         } catch (Exception e) {
  478.             e.printStackTrace();
  479.             return false;
  480.         }
  481.     }
  482.     /**
  483.      * 将list放入缓存
  484.      *
  485.      * @param key 键
  486.      * @param value 值
  487.      * @param time 时间(秒)
  488.      * @return
  489.      */
  490.     public boolean lSet(String key, List<Object> value, long time) {
  491.         try {
  492.             redisTemplate.opsForList().rightPushAll(key, value);
  493.             if (time > 0){
  494.                 expire(key, time);
  495.             }
  496.             return true;
  497.         } catch (Exception e) {
  498.             e.printStackTrace();
  499.             return false;
  500.         }
  501.     }
  502.     /**
  503.      * 根据索引修改list中的某条数据
  504.      * @param key 键
  505.      * @param index 索引
  506.      * @param value 值
  507.      * @return
  508.      */
  509.     public boolean lUpdateIndex(String key, long index, Object value) {
  510.         try {
  511.             redisTemplate.opsForList().set(key, index, value);
  512.             return true;
  513.         } catch (Exception e) {
  514.             e.printStackTrace();
  515.             return false;
  516.         }
  517.     }
  518.     /**
  519.      * 移除N个值为value
  520.      * @param key 键
  521.      * @param count 移除多少个
  522.      * @param value 值
  523.      * @return 移除的个数
  524.      */
  525.     public long lRemove(String key, long count, Object value) {
  526.         try {
  527.             Long remove = redisTemplate.opsForList().remove(key, count, value);
  528.             return remove;
  529.         } catch (Exception e) {
  530.             e.printStackTrace();
  531.             return 0;
  532.         }
  533.     }
  534. }
复制代码
2.5、Service层实现

在 UserService 中,创建数据时不仅将数据写入数据库,还将其缓存到 Redis 中。查询数据时,优先从 Redis 中获取,若 Redis 中不存在,则查询数据库并缓存结果。还会记载并输出 Redis 和数据库的查询时间:
  1. @Service
  2. public class UserService {
  3.     @Autowired
  4.     private UserMapper userMapper;
  5.     @Autowired
  6.     private RedisUtil redisUtil;
  7.     public User  getUserById(Long id){
  8.         //先从Redis中读取数据
  9.         String key = "user:"+id;
  10.         //判断该数据是否在Redis中
  11.         long redisStartTime = System.currentTimeMillis();
  12.         Object testUser = redisUtil.hasKey(key)?redisUtil.get(key):null;//先判断是否有,有就得到,没有就返回null
  13.         long redisEndTime = System.currentTimeMillis();
  14.         //存在的话则返回数据
  15.         if(testUser!=null){
  16.             System.out.println("Redis 查询时间: " + (redisEndTime - redisStartTime) + " ms");
  17.             return (User) testUser;
  18.         }
  19.         //不存在的话则从数据库中读取数据并将数据保存到Redis中
  20.         long dbStartTime = System.currentTimeMillis();
  21.         User user = userMapper.selectUserById(id);
  22.         long dbEndTime = System.currentTimeMillis();
  23.         System.out.println("数据库查询时间: " + (dbEndTime - dbStartTime) + " ms");
  24.         redisUtil.set(key,user);
  25.         return user;
  26.     }
  27. }
复制代码
2.6、Controller层实现

通过 UserController 提供 RESTful 接口,用于创建用户和查询用户信息:
  1. @RestController
  2. @RequestMapping("/test")
  3. public class UserController {
  4.     @Autowired
  5.     private UserService userService;
  6.     @GetMapping("/{id}")
  7.     public User test1(@PathVariable Long id) {
  8.         return userService.getUserById(id);
  9.     }
  10. }
复制代码
三、Redis相关知识点整理:

1. Redis 在缓存中的作用

在本项目中,Redis 主要用于缓存用户数据。通常,在频繁的数据库读利用中,每次查询数据库都会泯灭一定的时间和资源。而 Redis 作为一个基于内存的缓存,可以极大地减少对数据库的直接访问,提拔体系性能。
在下面我展示一下使用数据库与Redis查询数据的时间对比,还是很显着的,使用Redis能很洪流平地减少查询时间

2. Redis 与数据库的数据存取逻辑

在 UserService 中,我们实现了从 Redis 获取数据的逻辑:
  1. Object cachedUser = redisUtil.hasKey(key) ? redisUtil.get(key) : null;
复制代码
这里,我们起首判断 Redis 中是否已经缓存了对应用户数据(通过 redisUtil.hasKey(key))。如果缓存存在,则直接从 Redis 中获取数据,从而避免了数据库查询的延时。如果缓存不存在,则实行数据库查询,并将查询结果存入 Redis:
  1. User user = userMapper.selectUserById(id);
  2. redisUtil.set(key, user);
复制代码
这种 "缓存穿透" 的模式,确保了只有在 Redis 缓存未命中的环境下才会访问数据库,从而实现了高效的数据查询。
3. Redis 数据的存储与序列化

在 Redis 中存储复杂数据范例(如 Java 对象)时,使用了 Jackson2JsonRedisSerializer 来序列化对象:
  1. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  2. template.setValueSerializer(jackson2JsonRedisSerializer);
  3. template.setHashValueSerializer(jackson2JsonRedisSerializer);
复制代码
这段代码确保了 Redis 可以将 User 对象序列化为 JSON 字符串并存储在 Redis 中,当需要从缓存中获取数据时,再反序列化为 Java 对象。
四、总结:

    在本篇文章中,我们通过一个简朴的 Spring Boot 项目,联合 Redis 和 MySQL 实现了数据的存取,并比力了它们在时间上的差异。通过 Redis 的引入,可以明显提拔体系的性能,特别是在频繁读写的场景下,缓存策略能够有效减轻数据库的压力。
    本项目展示了怎样使用 Redis 来优化应用性能,以及 Redis 在现代应用架构中的告急性。如果你正在构建一个需要高性能、低延迟的应用,Redis 绝对是你不可或缺的技能之一。
    如果这篇文章有资助到你的话,就点个赞和关注吧,你的鼓励是我最大的动力!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金歌

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表