Le cache est une mémoire pour l'échange de données à grande vitesse, qui peut être utilisée pour accéder et exploiter rapidement les données.
Donnons un exemple simple.
Xiao Ming dirige un restaurant. Lors de son ouverture, en raison du manque de réputation et du peu de clients, l'entreprise n'était généralement pas très occupée lorsqu'il n'y avait rien à faire et se rendait en cuisine pour organiser la cuisine lorsque les invités. est venu. Avec le développement croissant des hôtels, les hôtels d'aujourd'hui sont différents du passé. Ils ont un grand nombre de clients stables, et ils sont même complets pendant certaines vacances. Selon la pratique précédente, cela ne fonctionnera certainement pas. Pendant la période de pointe pour les repas, les clients doivent attendre longtemps en raison de la lenteur de la préparation des repas, ce qui a provoqué des plaintes répétées auprès de l'hôtel.
Afin de résoudre ce problème, Xiao Ming a pensé à un moyen. Lorsqu'il est libre, il peut cuisiner des plats populaires à l'avance et les mettre dans l'armoire chauffante, puis les sortir et les réchauffer pendant la période de pointe des repas. puis servez-les directement. Cela évite le problème. Cette méthode résout le problème de la préparation lente des repas causée par un grand nombre de clients dans un court laps de temps. Cette méthode peut bien le gérer même pendant les périodes de pointe.
Le cœur de la mise en cache est de pré-stocker les ressources fréquemment consultées (lecture haute fréquence, écriture basse fréquence) dans un emplacement le plus proche de l'utilisateur et avec une vitesse d'accès plus rapide pour améliorer la vitesse d'accès.
Après avoir utilisé le cache, l'efficacité sera grandement améliorée, la consommation inutile de ressources sera réduite et l'expérience utilisateur sera améliorée.
Caractéristiques de redis :
redis prend en charge la persistance des données. Les données en mémoire peuvent être enregistrées sur le disque et peuvent être à nouveau ajoutées pour être utilisées lors du redémarrage.
redis prend non seulement en charge les données simples de type clé-valeur, mais fournit également le stockage de structures de données telles que la liste, l'ensemble, le zset, le hachage, etc.
redis prend en charge la sauvegarde des données, c'est-à-dire la sauvegarde des données dans master -mode esclave
Avantages de redis :
Extrêmement hautes performances - redis peut lire à une vitesse de 110 000 fois/s et écrire à une vitesse de 81 000 fois/s.
Types de données riches - redis prend en charge les opérations de type de données Chaînes, Listes, Hachages, Ensembles et Ensembles ordonnés pour les cas binaires.
Atomique - Toutes les opérations de Redis sont atomiques, ce qui signifie qu'elles seront soit exécutées avec succès, soit pas exécutées du tout en cas d'échec. Les opérations individuelles sont atomiques. Les opérations multiples prennent également en charge les transactions, c'est-à-dire l'atomicité, encapsulées par les instructions multi et exec.
Fonctionnalités riches, Redis prend également en charge la publication/l'abonnement, les notifications, l'expiration des clés et d'autres fonctionnalités
(1) Entièrement basé sur la mémoire, les données sont stockées en mémoire, la plupart des requêtes sont de la mémoire pure les opérations sont très rapides. Par rapport au stockage de données de fichiers sur disque traditionnel, cela évite la surcharge de lecture de la mémoire via les E/S du disque.
(2) La structure des données est simple et les opérations sur les données sont également simples. Chaque structure de données est supportée par une ou plusieurs structures de données spécialement conçues dans Redis. Redis utilise ces structures de données flexibles pour améliorer ses performances de lecture et d'écriture.
(3) L'utilisation d'un seul thread permet d'économiser beaucoup de temps de changement de contexte et de consommation de processeur. Il n'y a pas de condition de concurrence, il n'est pas nécessaire de prendre en compte divers problèmes de verrouillage, il n'y a pas d'opérations de verrouillage et de libération du verrouillage, et il n'y en aura pas. impasse entraînant une consommation de performances.
(4) En utilisant le modèle de thread basé sur le mécanisme de multiplexage IO, des liens simultanés peuvent être traités.
Database Structure de la table:
CREATE TABLE `blade_user` ( `id` bigint(20) NOT NULL COMMENT '主键', `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '000000' COMMENT '租户ID', `code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户编号', `user_type` int(11) DEFAULT NULL COMMENT '用户平台', `account` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '账号', `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码', `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '昵称', `real_name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '真名', `avatar` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像', `email` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '邮箱', `phone` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机', `birthday` datetime DEFAULT NULL COMMENT '生日', `sex` int(11) DEFAULT NULL COMMENT '性别', `role_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '角色id', `dept_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部门id', `post_id` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '岗位id', `create_user` bigint(20) DEFAULT NULL COMMENT '创建人', `create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_user` bigint(20) DEFAULT NULL COMMENT '修改人', `update_time` datetime DEFAULT NULL COMMENT '修改时间', `status` int(11) DEFAULT NULL COMMENT '状态', `is_deleted` int(11) DEFAULT '0' COMMENT '是否已删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用户表';
COMPLETE POM.xml Fichier:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.8</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.redis.demo</groupId> <artifactId>springboot-redis</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-redis</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </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> <!--mybatis-plus的springboot支持--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency> <!-- hutool 工具包,各种封装功能 一应俱全--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.5</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.41</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
Application.yml Fichier:
server: port: 8081 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://3.129.36.183:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8 username: root password: root #redis redis: host: 3.129.36.183 #Redis服务器连接端口 port: 6379 #Redis服务器连接密码 password: 123456 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志 # 将带有下划线的表字段映射为驼峰格式的实体类属性 map-underscore-to-camel-case: true #配置类型别名所对应的包 type-aliases-package: com.redis.demo.entity #配置SQL输出语句com.winsun.dataclean.mapper mapper-locations: com/redis/demo/dao/*.xml
RedisUtils:
package com.redis.demo.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * Redis工具类 * * @author */ @Component public class RedisUtils { @Autowired private RedisTemplate redisTemplate; // =============================common============================ /** * 指定缓存失效时间 * * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } // ============================String============================= /** * 普通缓存获取 * * @param key 键 * @return 值 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } // ================================Map================================= /** * HashGet * * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * * @param key 键 * @return 对应的多个键值 */ public Map<Object, Object> hmget(String key) { return redisTemplate.opsForHash().entries(key); } /** * HashSet * * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map<String, Object> map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map<String, Object> map, long time) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value, long time) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } /** * 判断hash表中是否有该项的值 * * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, -by); } // ============================set============================= /** * 根据key获取Set中的所有值 * * @param key 键 * @return */ public Set<Object> sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * * @param key 键 * @return */ public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } // ===============================list================================= /** * 获取list缓存的内容 * * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List<Object> lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * * @param key 键 * @return */ public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } }
RedisConfig:
package com.redis.demo.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.redis.demo.utils.MapUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import javax.annotation.PostConstruct; import java.util.Map; /** * @Author: laz * @CreateTime: 2023-02-20 11:55 * @Version: 1.0 * * 序列化 */ @Configuration public class RedisConfig { @Autowired private RedisTemplate redisTemplate; @PostConstruct public void init() { initRedisTemplate(); } private void initRedisTemplate() { RedisSerializer stringSerializer = redisTemplate.getStringSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setValueSerializer(stringSerializer); redisTemplate.setHashValueSerializer(stringSerializer); } }
Développer l'interface du mappeur
package com.redis.demo.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.redis.demo.entity.BladeUser; /** * <p> * 用户表 Mapper 接口 * </p> * * @author laz * @since 2023-03-09 */ public interface BladeUserMapper extends BaseMapper<BladeUser> { }
IBladeUserService:
package com.redis.demo.service; import com.baomidou.mybatisplus.extension.service.IService; import com.redis.demo.entity.BladeUser; import com.redis.demo.result.DealResult; /** * <p> * 用户表 服务类 * </p> * * @author laz * @since 2023-03-09 */ public interface IBladeUserService extends IService<BladeUser> { DealResult getById(Long id); }
BladeUserServiceImpl:
package com.redis.demo.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.redis.demo.constant.RedisConstants; import com.redis.demo.dao.BladeUserMapper; import com.redis.demo.entity.BladeUser; import com.redis.demo.result.DealResult; import com.redis.demo.service.IBladeUserService; import com.redis.demo.status.CacheNameStatus; import com.redis.demo.utils.RedisUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; /** * <p> * 用户表 服务实现类 * </p> * * @author laz * @since 2023-03-09 */ @Service public class BladeUserServiceImpl extends ServiceImpl<BladeUserMapper, BladeUser> implements IBladeUserService { @Autowired private RedisUtils redisUtils; @Override public DealResult getById(Long id) { String userKey = RedisConstants.CACHE_USER_KEY+id; Object user = redisUtils.get(userKey); if (!ObjectUtils.isEmpty(user)){ return DealResult.data(JSONUtil.toBean(JSONUtil.toJsonStr(user),BladeUser.class)); } BladeUser bladeUser = baseMapper.selectById(id); redisUtils.set(userKey, JSON.toJSONString(bladeUser)); return DealResult.data(bladeUser); } }
package com.redis.demo.controller; import com.redis.demo.result.DealResult; import com.redis.demo.service.IBladeUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RestController; /** * <p> * 用户表 前端控制器 * </p> * * @author laz * @since 2023-03-09 */ @RestController @RequestMapping("/bladeUser") public class BladeUserController { @Autowired private IBladeUserService bladeUserService; @RequestMapping("getById/{id}") public DealResult getById(@PathVariable("id")Long id){ return bladeUserService.getById(id); } }
Démarrez le projet et utilisez postman Accédez à cette interface et faites deux requêtes consécutives. Observez le temps de réponse :
Première fois :
Deuxième fois :
Vous pouvez voir que la première fois est de 3,34s et la deuxième fois est de 43ms. , l'efficacité est évidente Améliorez !
Sous réserve de la méthode 1
Ajoutez l'annotation @EnableCaching
dans la classe de démarrage@EnableCaching
注解
package com.redis.demo.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.redis.demo.constant.RedisConstants; import com.redis.demo.dao.BladeUserMapper; import com.redis.demo.entity.BladeUser; import com.redis.demo.result.DealResult; import com.redis.demo.service.IBladeUserService; import com.redis.demo.status.CacheNameStatus; import com.redis.demo.utils.RedisUtils; import lombok.AllArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; /** * <p> * 用户表 服务实现类 * </p> * * @author laz * @since 2023-03-09 */ @Service public class BladeUserServiceImpl extends ServiceImpl<BladeUserMapper, BladeUser> implements IBladeUserService { @Autowired private RedisUtils redisUtils; // @Override // public DealResult getById(Long id) { // // String userKey = RedisConstants.CACHE_USER_KEY+id; // Object user = redisUtils.get(userKey); // if (!ObjectUtils.isEmpty(user)){ // // return DealResult.data(JSONUtil.toBean(JSONUtil.toJsonStr(user),BladeUser.class)); // } // // BladeUser bladeUser = baseMapper.selectById(id); // redisUtils.set(userKey, JSON.toJSONString(bladeUser)); // return DealResult.data(bladeUser); // } @Cacheable(cacheNames = CacheNameStatus.BLADE_USER,keyGenerator = CacheNameStatus.KEY_GENERATOR) @Override public DealResult getById(Long id) { BladeUser bladeUser = baseMapper.selectById(id); return DealResult.data(bladeUser); } }
在配置类中添加自定义KeyGenerator
/** * 自定义KeyGenerator * @return */ @Bean public KeyGenerator simpleKeyGenerator() { return (o, method, objects) -> { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(o.getClass().getSimpleName()); stringBuilder.append("."); stringBuilder.append(method.getName()); stringBuilder.append("["); for (Object obj : objects) { if(obj.toString().indexOf("Vo@")!= -1) { Map<String, Object> map = MapUtil.getAttrFromModel(obj); stringBuilder.append("["); for(String item:map.keySet()) { stringBuilder.append(","); stringBuilder.append(map.get(item)); } stringBuilder.append(","); stringBuilder.deleteCharAt(stringBuilder.length() - 1); stringBuilder.append("]"); } else { stringBuilder.append(obj); stringBuilder.append(","); } } stringBuilder.append("]"); return stringBuilder.toString(); }; }
注:关于 @Cacheable
rrreee
Modifier la classe de configuration RedisConfig🎜🎜En configuration Ajouter un KeyGenerator personnalisé🎜rrreee🎜🎜🎜Note🎜🎜 à la classe : Concernant les paramètres de l'annotation@Cacheable
, si vous ne comprenez pas, vous pouvez cliquer pour le voir. 🎜🎜Redémarrez le projet, accédez à nouveau à l'interface ci-dessus et observez le temps de réponse : 🎜🎜Première fois : 🎜
La deuxième fois :
Vous voyez que la première fois est de 2.52s , La deuxième fois est de 44 ms, l'efficacité est considérablement améliorée !
Observez les données du cache grâce à l'outil de visualisation Redis :
#🎜🎜 ## 🎜🎜# En observant la taille des données mises en cache, nous pouvons voir que la première méthode est de 449 octets et la deuxième méthode est de 976 octets. Du point de vue de l'utilisation de la mémoire, estime le blogueur. que l'utilisation de la méthode
pour la mise en cache est plus appropriée, car cette méthode prend relativement peu de mémoire.Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!