Redis( stringRedisTemplate)添加缓存数据

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 在redis中添加缓存数据大致思路:1,从redis中获取数据,如果存在,直接返回客户端2,不存在,查询数据库,并写入redis缓存3,如果从数据库查询为空,返回错误信息4,写入redis缓存并返回数据

通过String类型添加商品数据

string思路:如果缓存中存在,需要把获取到的JSON数据转换为实体类

                   如果缓存不存在,则需要把查询到的数据转为JSON写入redis

1. public Result queryById(Long id) {
2. String shopKey = CACHE_SHOP_KEY + id;
3. //从redis中获取缓存
4. String shopJson = stringRedisTemplate.opsForValue().get(shopKey);
5. //判断是否存在
6. //如果存在直接返回查询结果
7. if (!StringUtils.isEmpty(shopJson)){
8. Shop shop = JSONUtil.toBean(shopJson, Shop.class);
9. return Result.ok(shop);
10.         }
11. //如果不存在,查询数据库
12. Shop shop = this.getById(id);
13. 
14. //如果数据库中也不存在,返回错误信息
15. if (shop==null){
16. return Result.fail("商品不存在");
17.         }
18. //将对象转为json存储
19. String shoptoJson = JSONUtil.toJsonStr(shop);
20. //如果存在写入redis缓存并返回查询信息
21.         stringRedisTemplate.opsForValue().set(shopKey,shoptoJson);
22. return Result.ok(shop);
23.     }

通过hash方式进行存储

hssh思路:如果缓存中存在,需要通过hutool工具类将map转换为对象并返回客户端

                 如果缓存中不存在,查询数据库,并将实体类转为map写入缓存,因为本文使用的是StringRedisTemple所以需要将实体类中非String类型字段转换为String类型进行存储,最终返回数据到客户端

1. public Result queryById(Long id) {
2. /**
3.          * 添加商户缓存,采用map形式
4.          */
5. String shopKey = CACHE_SHOP_KEY + id;
6. //如果缓存中有数据,直接返回客户端
7.         Map<Object, Object> shopMap = stringRedisTemplate.opsForHash().entries(shopKey);
8. if (shopMap!=null && shopMap.size()>0){
9. //将map转换为对象
10. Shop shop = BeanUtil.fillBeanWithMap(shopMap, new Shop(), false);
11. return Result.ok(shop);
12.         }
13. //如果缓存中没有数据,查询数据库并写入redis缓存
14. Shop shop = this.getById(id);
15. if (shop==null){
16. return Result.fail("不存在此商品");
17.         }
18. //将对象中的非String类型转为String类型
19.         Map<String, Object> shopMaps = BeanUtil.beanToMap(shop, new HashMap<>(),
20.                 CopyOptions.create().
21.                         setIgnoreNullValue(true).setFieldValueEditor((filedName, filedValue) -> {
22. if (filedValue == null) {
23.                                 filedValue = "0";
24.                             } else {
25.                                 filedValue = filedValue + "";
26.                             }
27. return filedValue;
28.                         }));
29. 
30.         stringRedisTemplate.opsForHash().putAll(shopKey,shopMaps);
31. return Result.ok(shop);
32.     }

通过List进行存储

通过List存储思路:通过list获取商品类型,判断是否命中缓存,如果命中缓存,遍历从Redis中获取到的集合并遍历设置到泛型为当前实体类对象的类型的集合,

                             如果缓存未命中,从数据库中查询数据,并获取到这个集合,遍历这个集合,并转换为JSON类型添加到一个泛型为String的集合,通过调用rightPushAll来完成redis的写入

1. public Result queryTypeList() {
2. //1.在redis中间查询,通过list获取商品类型
3.         List<String> shopTypeList = new ArrayList<>();
4.         shopTypeList = stringRedisTemplate.opsForList().range(CACHE_SHOP_TYPE_KEY,0,-1);
5. //2.判断是否缓存中了
6. //3.中了返回
7. if (!shopTypeList.isEmpty()){
8.             List<ShopType> typeList = new ArrayList<>();
9. for (String str:shopTypeList) {
10. ShopType shopType = JSONUtil.toBean(str, ShopType.class);
11.                 typeList.add(shopType);
12.             }
13. return Result.ok(typeList);
14.         }
15. //不存在,从数据库中查询
16.         List<ShopType> shopTypes = this.query().orderByAsc("sort").list();
17. if (shopTypes==null && shopTypes.size()>0){
18. return Result.fail("没有商品类型信息");
19.         }
20. //存在添加redis缓存
21. for(ShopType shopType : shopTypes){
22. String s = JSONUtil.toJsonStr(shopType);
23.             shopTypeList.add(s);
24.         }
25.         stringRedisTemplate.opsForList().rightPushAll(CACHE_SHOP_TYPE_KEY,shopTypeList);
26. return Result.ok(shopTypes);
27.     }

通过set进行存储

1. public List<Content> getLike() {
2. String key = "carousel:like";
3.         List<String> stringList = new ArrayList<>();
4.         stringList = stringRedisTemplate.opsForSet().randomMembers(key, 6);
5. if (!stringList.isEmpty()){
6.             List<Content> contents = new ArrayList<>();
7. for (String s : stringList) {
8. Content content = JSONUtil.toBean(s, Content.class);
9.                 contents.add(content);
10.             }
11. return contents;
12.         }
13. //查询数据库
14. //未命中查询数据库
15.         List<Content> contents = baseMapper.selectList(new QueryWrapper<Content>().eq("category_id",3));
16. 
17. //添加redis并返回6条数据
18.         List<Content> contentList = new ArrayList<>();
19. for (int i = 0; i < contents.size(); i++) {
20. String s = JSONUtil.toJsonStr(contents.get(i));
21.             stringRedisTemplate.opsForSet().add(key,s);
22. if (i<6){
23.                 contentList.add(contents.get(i));
24.             }
25.         }
26. return contentList;
27.     }

通过zset进行存储

1. public List<Movie> getpopularList() {
2.         List<Movie> movies = new ArrayList<>();
3.         Set<String> set = stringRedisTemplate.opsForZSet().reverseRange(MOVIE_POPULAR,0,-1);
4. //判断是否命中缓存
5. if (set != null && set.size()>0){
6.               List<String> zsetStrings = new ArrayList<>(set);
7. //命中返回
8. for (String zsetString : zsetStrings) {
9.                  movies.add(JSONUtil.toBean(zsetString,Movie.class));
10.               }
11. return movies;
12.           }
13.         movies = baseMapper.selectList(new QueryWrapper<Movie>().orderByDesc("score").last("limit 0,6"));
14. //写入redis数据库
15. for (Movie movie : movies) {
16. String s = JSONUtil.toJsonStr(movie);
17.               stringRedisTemplate.opsForZSet().add(MOVIE_POPULAR,s,movie.getScore());
18.           }
19. return movies;
20.     }
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
NoSQL Redis
Redis的数据淘汰策略有哪些 ?
Redis 提供了 8 种数据淘汰策略,分为淘汰易失数据和淘汰全库数据两大类。易失数据淘汰策略包括:volatile-lru、volatile-lfu、volatile-ttl 和 volatile-random;全库数据淘汰策略包括:allkeys-lru、allkeys-lfu 和 allkeys-random。此外,还有 no-eviction 策略,禁止驱逐数据,当内存不足时新写入操作会报错。
115 16
|
7天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
131 85
|
5天前
|
缓存 NoSQL Redis
Redis经典问题:数据并发竞争
数据并发竞争是大流量系统(如火车票系统、微博平台)中常见的问题,可能导致用户体验下降甚至系统崩溃。本文介绍了两种解决方案:1) 加写回操作加互斥锁,查询失败快速返回默认值;2) 保持多个缓存备份,减少并发竞争概率。通过实践案例展示,成功提高了系统的稳定性和性能。
|
5天前
|
缓存 监控 NoSQL
Redis经典问题:数据不一致
在使用Redis时,缓存与数据库数据不一致会导致应用异常。主要原因包括缓存更新失败、Rehash异常等。解决方案有:重试机制、缩短缓存时间、优化写入策略、建立监控报警、定期验证一致性、采用缓存分层及数据回滚恢复机制。这些措施可确保数据最终一致性,提升应用稳定性和性能。
|
5天前
|
缓存 监控 NoSQL
Redis经典问题:缓存穿透
本文详细探讨了分布式系统和缓存应用中的经典问题——缓存穿透。缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致大量请求直接落到数据库上,可能引发数据库崩溃或性能下降。文章介绍了几种有效的解决方案,包括接口层增加校验、缓存空值、使用布隆过滤器、优化数据库查询以及加强监控报警机制。通过这些方法,可以有效缓解缓存穿透对系统的影响,提升系统的稳定性和性能。
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
1月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
在项目中,为了解决Redis与Mysql的数据一致性问题,我们采用了多种策略:对于低一致性要求的数据,不做特别处理;时效性数据通过设置缓存过期时间来减少不一致风险;高一致性但时效性要求不高的数据,利用MQ异步同步确保最终一致性;而对一致性和时效性都有高要求的数据,则采用分布式事务(如Seata TCC模式)来保障。
68 14
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
43 5
|
1月前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用哈希槽分区算法,共有16384个哈希槽,每个槽分配到不同的Redis节点上。数据操作时,通过CRC16算法对key计算并取模,确定其所属的槽和对应的节点,从而实现高效的数据存取。
52 13
|
1月前
|
存储 NoSQL Redis
Redis的数据过期策略有哪些 ?
Redis 采用两种过期键删除策略:惰性删除和定期删除。惰性删除在读取键时检查是否过期并删除,对 CPU 友好但可能积压大量过期键。定期删除则定时抽样检查并删除过期键,对内存更友好。默认每秒扫描 10 次,每次检查 20 个键,若超过 25% 过期则继续检查,单次最大执行时间 25ms。两者结合使用以平衡性能和资源占用。
50 11