微服务系统面经之三: 以秒杀系统为例-多级缓存及其更新机制

22 多级缓存(百度一面)

22.1 你用了什么缓存

答:本地内存+redis

22.2 内存标记是如何被使用被更新的

22.3 什么时候修改这个第一层缓存(内存标记),把它改为false

答:当redis预减库存为0的时候,这个就需要改为false

22.4 这个内存标记可以被称为第二级缓存吗?(我答错了)

22.4.1 内存标记和redis预减库存的操作,哪一个属于一级缓存哪一个属于二级

在秒杀系统设计中,"内存标记"和"Redis预减库存"都是优化手段,旨在减少对数据库的访问以提高系统的性能。但在缓存的层级分类中,这两者的位置可以如下解释:

  1. 内存标记:它直接在应用程序的内存中进行,速度非常快。因为这种操作不需要与任何外部系统通信,所以它通常被视为一级缓存

  2. Redis预减库存:Redis是一个外部的内存存储系统,虽然它非常快,但与直接在应用程序的内存中进行操作相比,访问Redis会涉及到网络通信的延迟。因此,从缓存的层级分类角度来看,Redis通常被视为二级缓存

所以,简而言之,内存标记是一级缓存,而Redis预减库存是二级缓存。

22.4.2 一级、二级缓存的区别标志是什么呢

一级缓存和二级缓存的区别通常基于以下特性或标志来定义:

  1. 存储位置

    • 一级缓存:通常存储在事务或会话的上下文中,这意味着它是局部的,仅与单个会话或线程相关。例如,在某些ORM框架中,一级缓存是与单个会话关联的。
    • 二级缓存:通常是全局的,它存储在进程或应用之外的位置,并可供多个会话或线程共享。例如,分布式缓存系统如Redis或Memcached。
  2. 生命周期

    • 一级缓存:生命周期通常限于单个会话或事务。会话结束时,缓存中的数据也可能被清除。
    • 二级缓存:生命周期超出单个会话,通常基于时间或容量失效策略来管理。
  3. 数据共享性

    • 一级缓存:因为它是局部的,所以不会被多个会话或线程共享。
    • 二级缓存:可以被多个会话、线程或甚至是多个应用实例共享。
  4. 访问速度

    • 一级缓存:访问速度非常快,因为它通常在应用程序的内存中。
    • 二级缓存:虽然也是非常快的,但由于可能涉及到进程间或网络通信,所以相对较慢。
  5. 失效策略

    • 一级缓存:通常在会话结束或事务完成后自动失效。
    • 二级缓存:通常基于具体的失效策略,如LRU、TTL等。
  6. 复杂性

    • 一级缓存:通常更简单,自动管理。
    • 二级缓存:可能需要更多的配置和管理,尤其是当涉及到分布式缓存系统时。

根据上述特点,开发者可以根据实际需要选择使用一级缓存、二级缓存或两者结合,以优化应用程序的性能。

22.4.3 我觉得可以根据距离cpu的逻辑远近来判断,比如本地内存标记不需要网络通信,所以是一级,redis需要网络通信,所以是二级 另外一种角度看,数据是首先同步到redis,然后再同步到内存标记的

确实,根据数据存取的速度和距离CPU的逻辑远近来判断缓存层级是非常直观的方式。在计算机架构中,这种分类方式常被用来描述CPU的缓存层级(L1、L2、L3等),其中距离CPU核心越近、速度越快的缓存被视为更低的层级。

对于应用层面的缓存:

  • 一级缓存:通常指直接存储在应用进程中的缓存,如Java对象在JVM堆上的存储。这种缓存的访问速度极快,不涉及任何跨进程或网络通信。

  • 二级缓存:涉及到跨进程通信或网络通信的缓存,如Redis、Memcached等分布式缓存系统。虽然它们仍然是内存存储,但由于涉及通信,访问速度相对较慢。

你的观点完全成立。如果数据首先同步到Redis然后再同步到内存标记,那么可以将Redis视为一种“前置缓存”或“缓冲层”,而应用内存中的标记则可以视为更接近实际数据处理和业务逻辑的一级缓存。

这种层级化的缓存策略使得应用能够更加灵活地处理高并发情况,同时确保数据的一致性和系统的响应速度。

22.5 内存标记和redis缓存的区别是什么呢?

答:使用内存标记就不需要和远程主机进行网络通信

23 一致性与缓存和mysql的更新机制(百度一面)

23.1 如果有一部分流量进来了之后,就卡在这个边界点,你怎么去判断?如果秒杀第10件商品的时候,有两个请求同时打到后端,有没有可能这两个请求都进到你的消息队列中去?

答:有可能的,因为redission可能会发生数据丢失,redis集群本身只能保证最终一致性

23.2 如果有一主多从的话,是不是可能存在多个流量进来呢?

答:对,但是这种概率很低,因为一个redis集群连续发生多次主从切换的可能性很小

23.3 前端这个时候,你会提示它在等待吗?

答:对,会显示排队中,客户端会不断轮询后端暴露出来的一个查询订单的接口,查看是否存在,这个接口会增加这个订单到redis缓存中

23.3.1 为什么这个时候数据库和redis的同步机制是先更新mysql,后更新缓存?难道不存在不一致问题吗?

答:这个时候,客户端只涉及到查询订单操作,而不涉及到修改,而且只有这一个服务端线程会修改redis缓存,所以可以采用先更新mysql,再删除redis

23.4 如果用户下单后没多久又取消订单了怎么办?如果没有支付怎么办(误区:(1)把这两个弄成了一个事情,库存回退没有说,两级缓存更新没有说)

答:

当用户下单后没多久又取消订单,或者下单后未支付,系统需要有一套相应的处理机制。这些机制通常涉及订单的生命周期管理、库存管理、支付超时等。以下是一些常见的处理方式:

  1. 订单取消

    • 库存回滚:当用户取消订单,前端会向指定的接口立即发送请求,系统应立即将对应的商品库存数量回滚。
    • 订单状态管理:订单应有多个状态,如“已创建”、“已支付”、“已取消”等。当用户取消订单时,系统应将订单状态更改为“已取消”。
    • 库存回退和缓存更新:会将这个库存回退到mysql的商品表中,然后会删除redis中相应的订单,同时删除redis的关于该库存信息的缓存,然后再将业务服务器中的该商品是否售罄的缓存更新为false
  2. 未支付的订单

    • 支付超时机制:为订单设定一个支付超时时间(例如15或30分钟)。如果用户在这个时间内没有完成支付,系统自动将订单状态更改为“已取消”并回滚库存。
    • 超时提醒:当订单即将到达超时时间时,可以通过短信、邮箱或应用内通知提醒用户支付。
    • 定期检查:后端可以使用定时任务或其他机制定期检查未支付的订单,并根据其创建时间处理超时订单。
    • 库存回退和缓存更新:(基本逻辑和订单取消的相应逻辑相同)

总之,对于用户的取消订单或未支付行为,系统应该有一套完整的策略和流程,确保商家的利益和其他用户的正常购买体验不受影响。

23.5 你的一级缓存如何更新呢?这是不是涉及到了多个本地内存机器的内存标记的更新呢?

答:

一级缓存通常指的是业务服务器本地的内存缓存,例如Java中的ConcurrentHashMap或其他本地缓存工具。更新一级缓存的方法和策略如下:

  • 数据变动触发:当有关键数据(如库存)变动时,我们需要同时更新一级缓存中的相关数据。
  • 多机器同步问题:在分布式环境中,可能有多个业务服务器实例,因此当一级缓存的数据在一个实例中被修改时,我们需要确保其他实例的缓存数据也被相应地更新。这通常通过消息中间件如Kafka、RabbitMQ等来实现,当一个实例更新了缓存,它会发送一个消息到消息中间件,其他实例监听到这个消息后会更新自己的一级缓存。
  • 定期刷新:一些数据可能不是经常变动,但为了确保数据的时效性和准确性,可以设置一个定期刷新的策略,例如每隔一段时间从数据库或二级缓存(如Redis)中重新加载数据。

23.6 你的缓存更新会不会造成并发的冲突呢?比如客户端线程在读,服务端线程在写

答:

缓存并发的问题确实是一个需要关注的点。根据不同的缓存类型和策略,处理方式也会有所不同。

  • Redis缓存:Redis是单线程模型,它确保了每次只有一个命令在执行,因此不会有并发冲突。但在分布式应用中,多个客户端同时发送命令到Redis可能会造成读旧数据的情况。为了避免这种情况,可以使用Redis的事务功能或乐观锁来确保数据的一致性。

  • 本地内存缓存:在多线程环境中,本地缓存可能会出现并发的问题。例如,当一个线程正在更新缓存数据时,另一个线程可能正在读取这些数据。为了解决这个问题,可以使用并发工具,如Java中的ConcurrentHashMap或ReadWriteLock。ConcurrentHashMap允许多个读线程并发进行,但写操作会被锁定,确保每次只有一个线程可以写入。ReadWriteLock也提供了类似的功能,但提供了更细粒度的控制。

综上所述,确保缓存的并发安全是关键,需要根据实际情况选择合适的工具和策略来实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/76534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vmware设置桥接模式后ip设置

网络连接方式设置 找到虚拟机里机器的网络设置 左边是宿主机,右边是虚拟机,按照这个设置就可以上网了(IP指定一个没有占用的值,子网掩码和网关设置成一样的)就可以联网了。 over~~

Vue2屎山代码大盘点

前言 相比其他的框架来说,Vue中更容易产出屎山代码;因为Vue中的options就是一个大对象,导致js本身的很多检测都失效了,比如一个函数没有用到的话会“变灰”,template中代码提示比较少,较多的mixins等等&…

mobaXterm使用pycharm

首先去pycharm的官网PyCharm: the Python IDE for Professional Developers by JetBrains 下载pycharm(选择linux的community版本即可) 下载后的压缩包拖拽到mobaXterm如下位置: 进入压缩包所在的文件夹(图中这个位置是root目录&…

记一次线程堵塞(挂起)导致消息队列积压

1 背景 A服务作为生产者,每天发送上千万的mq消息,每一个消息包含500个用户ids数据。B服务作为消费者,接受MQ消息并通过http调用第三方请求进行业务处理,消费组启用了rabbitmq的多线程消费组,一个实例并发40个mq消费者…

Git Cherry Pick命令

1. 简介 Git是一款分布式版本控制系统,它提供了许多强大的功能来管理代码的版本和变更。其中之一就是cherry-pick命令,它允许我们选择某个分支上的一个或多个提交,并将它们应用到当前分支上。这个功能非常有用,可以帮助我们在不合…

Python文件操作(02):读文件

一、读文本文件 打开文件读文件内容关闭文件 1、在读取文件内容后进行解码操作 """ 1. 打开文件- 路径:相对路径:当前项目(读文件.py)所在的目录下查找需要读取的文件绝对路径:文件--右键--Copy Pat…

Java中的Maven是什么?

Maven是一个开源的项目管理和构建工具,用于Java项目的构建、依赖管理和项目信息管理。它提供了一种标准的项目结构、规范的构建过程和丰富的插件生态系统,简化了项目的管理和构建过程。 Maven基于项目对象模型(Project Object Model&#xf…

四、Go中的条件判断和for循环

一、if条件判断 代码: package mainimport "fmt"func main() {//if 条件判断score : 50judgingGrades(score)}/* * go语言中 if的用法 */ func judgingGrades(score int) {if score > 90 {fmt.Println("优等生")} else if score > 80 |…

Prompt Tuning训练过程

目录 0. 入门 0.1. NLP发展的四个阶段: Prompt工程如此强大,我们还需要模型训练吗? - 知乎 Prompt learning系列之prompt engineering(二) 离散型prompt自动构建 Prompt learning系列之训练策略篇 - 知乎 ptuning v2 的 chatglm垂直领域训练记…

读高性能MySQL(第4版)笔记05_优化服务器设置

1. 除非遇到异常情况,否则不需要调整配置 1.1. 不要“调优”服务器,不要使用比率、公式或“调优脚本”作为设置配置变量的基础 1.1.1. 在互联网上搜索配置建议并不总是一个好主意,你会在博客、论坛等找到很多糟糕的建议 1.1.2. 很难判断谁…

Python机器学习、深度学习在气象、海洋、水文领域实践应用

Python是功能强大、免费、开源,实现面向对象的编程语言,能够在不同操作系统和平台使用,简洁的语法和解释性语言使其成为理想的脚本语言。除了标准库,还有丰富的第三方库,Python在数据处理、科学计算、数学建模、数据挖…

SpringBoot+Vue 整合websocket实现简单聊天窗口

效果图 1 输入临时名字充当账号使用 2 进入聊天窗口 3 发送消息 &#xff08;复制一个页面&#xff0c;输入其他名字&#xff0c;方便展示效果&#xff09; 4 其他窗口效果 代码实现 后端SpringBoot项目&#xff0c;自行创建 pom依赖 <dependency><groupId…

uni-app 使用uCharts-进行图表展示(折线图带单位)

前言 在uni-app经常是需要进行数据展示&#xff0c;针对这个情况也是有人开发好了第三方包&#xff0c;来兼容不同平台展示 uCharts和pc端的Echarts使用差不多&#xff0c;甚至会感觉在uni-app使用uCharts更轻便&#xff0c;更舒服 但是这个第三方包有优点就会有缺点&#xf…

vue 部署到本机IIS 部署 SPA 应用

安装 URL Rewrite Works With: IIS 7, IIS 7.5, IIS 8, IIS 8.5, IIS 10 URL Rewrite : The Official Microsoft IIS Site 目前电脑IIS是6版本的&#xff0c;以下的方法不太合适操作。目前用Nginx部署&#xff0c;够用了。 nginx配置参考&#xff1a; uni-app 前面项目&am…

Segment Anything Model(SAM)论文解读

一、引言 在这项工作中&#xff0c;作者的目标是建立一个图像分割的基础模型。也就是说&#xff0c;寻求开发一个提示模型&#xff0c;并使用一个能够实现强大泛化的任务在广泛的数据集上对其进行预训练。有了这个模型&#xff0c;使用即时工程解决新数据分布上的一系列下游分…

【rpc】Dubbo和Zookeeper结合使用,它们的作用与联系(通俗易懂,一文理解)

目录 Dubbo是什么&#xff1f; 把系统模块变成分布式&#xff0c;有哪些好处&#xff0c;本来能在一台机子上运行&#xff0c;为什么还要远程调用 Zookeeper是什么&#xff1f; 它们进行配合使用时&#xff0c;之间的关系 服务注册 服务发现 动态地址管理 Dubbo是…

Nacos docker实现nacos高可用集群项目

目录 Nacos是什么&#xff1f; Nacos在公司里的运用是什么&#xff1f; 使用docker构建nacos容器高可用集群 实验规划图&#xff1a;​编辑 1、拉取nacos镜像 2、创建docker网桥&#xff08;实现集群内的机器的互联互通&#xff08;所有的nacos和mysql&#xff09;&#x…

环境变量与Path环境变量

“环境变量”和“path环境变量”其实是两个东西&#xff0c;这一点大家一定要区分开&#xff0c;不要混为一谈。 “环境变量”是操作系统工作环境设置的一些选项或属性参数。每个环境变量由变量名和文件路径组成的&#xff0c;可以设置很多个环境变量。 我们一般使用环境变量…

冒泡排序、选择排序、插入排序、希尔排序

冒泡排序 基本思想 代码实现 # 冒泡排序 def bubble_sort(arr):length len(arr) - 1for i in range(length):flag Truefor j in range(length - i):if arr[j] > arr[j 1]:temp arr[j]arr[j] arr[j 1]arr[j 1] tempflag Falseprint(f第{i 1}趟的排序结果为&#…

人生中第一次向开源项目提交PR记录

git了解很久了&#xff0c;但是就是没有向大一点的项目提交过pr&#xff0c;都是自己瞎折腾&#xff0c;记录一下开源项目提交PR过程&#xff0c;省略的过程可以参考&#xff1a; https://www.runoob.com/git/git-tutorial.html&#xff0c;这个里面包括安装&#xff0c;使用&a…