• 【苍穹外卖 | 项目日记】第六天


    前言:

            截止到今天为止,我自身感觉是有很大的进步,今天也一个人独立写了很多的接口,相比较于第一次简直是天差地别。今天在听课的时候也有很多的收获。开心

    目录

    前言:

    今日完结任务:

    今日收获:

    1.实现了缓存菜品的功能:

    2.实现了缓存套餐的功能:

    3.购物车相关接口:

    杂项知识点:

    总结:


     

    今日完结任务:

    • 1.实现了缓存菜品功能
    • 2.实现了缓存套餐功能
    • 3.实现了添加购物车接口
    • 4.实现了查看购物车接口
    • 5.实现了清空购物车接口
    • 6.实现了删除购物车商品接口

    今日收获:

    1.实现了缓存菜品的功能:

    这个功能的出发点是因为:在项目上线之后,会有大量的并发请求,而我们以前在查询菜品的时候,采用的是直接从数据库中读取数据返回给前端的操作。但这是一个I/O操作,大量的并发I/O操作会狠狠的拷打我们的后端服务器。而用户端的体验也会大大下降(查询数据满慢造成卡顿感受)

    因此为了提高我们的用户效率,我们采用这样一种思想:建立一块缓存区,在用户查询对应数据的时候,先看看缓存区有没有,如果缓存区有,直接发送缓存区中的数据,如果缓存区没有,再查询数据库,并且把查询到的数据同时存到缓冲区中,便捷下次查询的效率。

    这种思想其实很常见,我们的DNS服务商也在使用这种思想,他们会缓存常见域名对应的IP地址,这样在DNS转换的时候,就不需要再向各级地址进行查询,大大优化了耗时

    而我们建立缓存区的方法是使用Redis数据库,在前面我们就介绍过Redis,他是一个存储在内存中的键值类型的数据库,这大大优化了查询效率。

    在这里我们贴一段在查询菜品的时候应用Redis优化的代码

     其实Spring 就已经为我们提供了通过注解的方式来解决这些问题,在后面我们也会逐一介绍

    2.实现了缓存套餐的功能:

    基于和缓存菜品一样的需求,我们来实现缓存套餐,而我们在这里用到了一个依赖:Spring Cache

            Spring Cache是Spring框架提供的一个缓存抽象层,它允许开发者轻松地在应用程序中添加缓存功能。通过使用Spring Cache,开发者可以将常用的数据或计算结果缓存起来,以提高应用程序的性能和响应速度。

    Spring Cache的工作原理是基于AOP(面向切面编程)和注解。开发者只需在相应的方法上添加缓存注解,Spring Cache就会使用缓存来缓存方法的返回值。当下次再次调用该方法时,Spring Cache会首先查询缓存中是否存在该返回值,并直接返回缓存结果,避免了重复的计算或数据库查询。

    Spring Cache支持多种缓存存储的后端实现,包括基于内存的缓存(如ConcurrentMapCache)、基于Redis的分布式缓存、基于Ehcache的本地缓存等。开发者可以根据项目需求选择合适的缓存实现。

    引入依赖:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-cacheartifactId>
    4. dependency>

    然后我们就可以通过调用相关注解的方式来达到缓存套餐的功能:(在这里我们的底层缓存实现还是redis)


     他的常用注解我会在后面介绍

    3.购物车相关接口:

            购物车相关接口其实收获不大,还是普通的curd操作。但是一通写下来确实是让我的熟练度更加好了

    杂项知识点:

    1.如何保持redis与数据库中的数据的一致性?

    因为我们在添加redis作为缓冲区之后,如果缓冲区中存在数据,我们是直接从缓冲区拿数据的,如果我们更改了数据库,可能就会造成数据库与缓冲区数据不一致的情况。

    1. 读写双写(Write-through):在更新数据库时,同时更新Redis缓存。这意味着在写入数据库的同时,将相同的数据写入Redis缓存。这种方式确保了数据库和缓存中的数据始终保持一致。但是需要注意的是,双写操作会增加系统的写入负载和延迟,并且需要保证写入操作的原子性。

    2. 读写更新(Write-behind):在更新数据库时,延迟更新Redis缓存。这种方式先更新数据库,然后异步地更新Redis缓存,以提高写入的性能和响应速度。在这种情况下,可能会出现一小段时间内数据库和缓存数据的不一致,但后续的读取操作会从数据库中获取最新的数据并更新缓存。

    3. 缓存失效策略:通过在缓存中设置适当的过期时间或失效策略,确保缓存中的数据在一定时间后会过期并从数据库中重新加载。这样可以保证在数据更新或过期后,下一次读取操作将从数据库中获取最新的数据,并更新缓存。这种方式适用于数据变化不频繁、对数据实时性要求不高的场景。

    4. 发布订阅模式(Pub/Sub):使用Redis的发布订阅功能,当数据库中的数据发生变化时,通过发布消息的方式通知订阅者(Redis缓存)进行更新。这样可以保证在数据发生变化时,及时通知Redis缓存更新,以保持数据的一致性。

     2.什么是redis三大问题:穿透,击穿,雪崩

    1. 穿透(Cache Penetration):当一个不存在的键被频繁查询时,会导致缓存无效并且每次查询都需要访问数据库。这种情况下,恶意用户可以通过构造不存在的键来绕过缓存,直接请求数据库。这不仅浪费了数据库的资源,还可能导致数据库压力过大。为了解决穿透问题,可以使用布隆过滤器或者在查询得到空结果时也进行缓存,设置一个较短的过期时间。

    2. 击穿(Cache Breakdown):当一个热点键过期或被清除时,同时又有大量的请求访问该键,导致这些请求直接访问数据库,称为击穿。这种情况下,数据库会承受巨大的压力,可能导致宕机或性能下降。为了解决击穿问题,可以使用互斥锁或者分布式锁,保证只有一个请求能够访问数据库,并在请求获取到数据后更新缓存。

    3. 雪崩(Cache Avalanche):当大量的缓存键在同一时间失效,或者缓存服务器发生故障,导致大量的请求直接访问数据库,称为雪崩效应。这种情况下,数据库会承受巨大的压力,可能导致宕机或性能下降。为了解决雪崩问题,可以采用多级缓存架构,将请求分散到多个缓存服务器,或者使用热点数据预加载的方式,提前加载热门数据到缓存中。

     3.spring cache中的@Cacheable、@CachePut、@CacheEvict  @三个注解

    1. @Cacheable注解:用于在方法执行前检查缓存中是否存在对应的值,如果存在则直接返回缓存结果,否则执行方法并将返回值存入缓存中。该注解常用于读取操作。

      1. @Cacheable(cacheNames = "myCache", key = "#param")
      2. public Object myMethod(String param) {
      3. // 方法体
      4. }
      • cacheNames:指定缓存名称,对应于配置中的缓存管理器中的缓存名。
      • key:指定缓存的键,可以通过SpEL表达式指定,例如#param表示使用方法的参数作为键。
    2. @CachePut注解:用于将方法的返回值存入缓存中,无论缓存中是否已存在该键,都会将返回值存入缓存。该注解常用于更新操作。

      1. @CachePut(cacheNames = "myCache", key = "#param")
      2. public Object myMethod(String param) {
      3. // 方法体
      4. }
      • cacheNames:缓存名称。 
      • key:缓存键。
    3. @CacheEvict注解:用于从缓存中清除对应的值。该注解常用于删除操作。

      1. @CacheEvict(cacheNames = "myCache", key = "#param")
      2. public void myMethod(String param) {
      3. // 方法体
      4. }
      • cacheNames:缓存名称。
      • key:缓存键。

     除了这三个注解以外,还有一个启动类注解@EnableCaching标识在启动类上,表示开启缓存注解功能

    总结:

            创造缓冲区来减少对数据库的直接查询,提高访问效率是一个不错的思想,他巧妙的利用的Redis的存储特性。在实际业务开发中也是一个比较常见的需求,因此今天还是有学到一点好东西的。

    如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

    69e9169c980f43e0aad31ff9ada88a9c.png

     

  • 相关阅读:
    收银系统十大排名(2023年十大收银软件品牌排行榜)
    如何用CAN-EYE获取植被参数数据?
    封仲淹:OceanBase社区版4.0未来畅想
    多层感知机
    【Python自学笔记】Python编程:使用sys和argparse配置和使用带参数的命令行
    【JAVA】普通IO数据拷贝次数的问题探讨
    15设计模式-行为型模式-观察者模式
    【 C++ 】模板初阶 —— 函数模板、类模板
    Python机器学习-多元分类的5种模型
    每天分享几个面试题(六)
  • 原文地址:https://blog.csdn.net/fckbb/article/details/133870093