秋招面经记录

news2024/11/20 1:43:44

秋招面经记录

  • MySQL
  • Redis
  • 项目
  • 分布式
  • 框架
  • java
  • 网络
  • 数据结构
  • 设计模式
  • HR
  • 手撕

MySQL

  1. Mysql中有1000万条数据,每次查询10条,该如何优化(答:Limit子查询优化)
    在这里插入图片描述在这里插入图片描述

    select t.* from t_topic t LIMIT 90000,10;
    对上面的mysql语句说明:limit 90000,10的意思扫描满足条件的90010行,扔掉前面的90000行,返回最后的10行,问题就在这里,如果是limit 100000,100,需要扫描100100行,并且此处查询是普通查询。

    优化:建立id索引
    select * from t_topic where id>=(select id from t_topic limit 90000,1) limit 10;
    先使用索引查询到第90000行数据的主键值,然后在根据主键值查询后续的数据

    gpt: 如果查询的数据是索引列,并且该索引是有序的(例如,主键索引或普通索引),
    那么LIMIT 90000, 1 的执行方式会稍有不同。在这种情况下,
    DBMS 可能会利用索引的有序性来直接定位和返回指定范围内的数据,而无需扫描和跳过大量的记录。

  2. 有了解过mysql索引吗

  3. 项目中使用到索引的情况(答:覆盖索引,避免回表)

  4. B+树和b树区别

  5. 内连接和外连接区别
    在这里插入图片描述

  6. Innodb 和myisam区别

     (1)事务支持:
     	InnoDB是支持事务处理的存储引擎,它遵循ACID(原子性、一致性、隔离性和持久性)特性。
     	它支持提交(COMMIT)和回滚(ROLLBACK)操作,适用于需要处理并发操作和保证数据完整性的应用程序。
     	MyISAM不支持事务处理,不能进行回滚操作。因此,在并发访问下可能会导致数据不一致的问题。
     (2)锁机制:
     	InnoDB使用行级锁(row-level locking),这意味着在同时处理多个事务时,只锁定受影响的行,
     	而不是整个表。这样可以提高并发性能,允许多个事务同时读取和修改不同的行。
     	MyISAM使用表级锁(table-level locking),这意味着在执行写操作时会锁定整个表,
     	这会导致并发性能受限,因为其他事务无法同时读取或写入相同的表。
     (3)外键支持:
     	InnoDB支持外键约束(foreign key),可以通过定义外键关系来保证数据的引用完整性。
     	MyISAM不支持外键约束,无法自动检查和强制执行关联表之间的引用完整性。
     (4)崩溃恢复:
     	InnoDB具有崩溃恢复能力,可以在数据库异常崩溃时进行自动恢复,并保持数据的一致性。
     	MyISAM在崩溃时无法进行自动恢复,可能会导致数据损坏或丢失。
     (5)全文索引:
     	InnoDB从MySQL 5.6版本开始支持全文索引(Full-Text Index),可以用于高效地进行全文搜索。
     	MyISAM一直以来都支持全文索引,并提供了一些额外的全文搜索功能。
     综上所述,InnoDB适用于需要事务支持、并发性能较高、数据完整性要求较高的应用程序;
     而MyISAM适用于对事务支持要求不高、读操作较多、并发性能要求不高的应用程序。根据实际需求选择合适的存储引擎是很重要的。
    
  7. explain命令查询出的字段

     (1)id:表示查询的标识符,每个子查询都有一个唯一的标识符。
     (2)select_type:表示查询的类型。
     	SIMPLE:简单查询,不包含子查询或UNION查询。
     	PRIMARY:最外层查询。
     	SUBQUERY:子查询(非UNION子查询)。
     	DERIVED:派生表(FROM子句中的子查询)。
     	UNION:UNION连接的第二个或后续查询。
     	UNION RESULT:UNION的结果。
     	table:表示访问的表名。
     (3)type:表示连接类型或访问类型。
     	const:通过索引返回的常量值查询。
     	eq_ref:使用唯一索引或主键进行连接。
     	ref:使用非唯一索引进行连接。
     	range:使用索引范围查询。
     	index:全表扫描,遍历整个索引树。
     	all:全表扫描,没有使用索引。
     (4)possible_keys:表示可能选择的索引。
     
     (5)key:表示实际选择的索引(可能为NULL)。
     
     (6)key_len:表示索引字段的长度。
     
     (7)ref:表示连接时使用的字段。
     
     (8)rows:表示预计需要扫描的行数。
    
     (9)filtered:表示通过条件过滤后的比例。
     
     (10)Extra:表示额外的信息。
     	Using index:只使用了索引树,不需要访问表数据。
     	Using where:在获取数据之前进行了WHERE过滤。
     	Using temporary:需要创建临时表来处理查询。
     	Using filesort:需要额外的排序操作。
     	Using join buffer:需要使用连接缓冲区。
     	Impossible where:WHERE子句总是返回false,不会有匹配的行。
     	Select tables optimized away:查询可以被优化为常量查询。
    
  8. B+树结点区别

  9. 数据库中有某个二级索引name,有若干行数据为null,现在使用name is null统计null的行数,是否会走索引。

     例如:select * from table where name is null
     非聚簇索引是通过B+树的方式进行存储的,null值作为最小数看待,全部放在树的最左边,形成链表,
     如果获取is null的数据,可以从最左开始 直到找到记录不是null结束。 
     决定is null或者is not null走不走索引取决于执行成本,是否走索引取决于优化器。
     通过非聚簇索引查询需要回表才能获得记录数据(覆盖索引除外),那么在这过程中优化器发现回表次数太多,
     执行成本已经超过全表扫描.例如:几乎所有数据都命中,都需要回表.这个时候,优化器会放弃索引,走效率更高全表扫描 
    
  10. 索引删除和添加是否会改变整个索引结构
    在这里插入图片描述

Redis

  1. Redis中bitmap的原理,如何做签到统计

     Bitmap,即位图,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。BitMap通过最小的单位bit来进行0|1的设置,
     表示某个元素的值或者状态,时间复杂度为O(1)。Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型。
     String 类型是会保存为二进制的字节数组,所以,Redis 就把字节数组的每个 bit 位利用起来,用来表示一个元素的二值状态,
     你可以把 Bitmap 看作是一个 bit 数组。由于 bit 是计算机中最小的单位,使用它进行储存将非常节省空间,
     特别适合一些数据量大且使用二值统计的场景。
    
  2. redis持久化方式,区别

  3. redis的使用场景
    在这里插入图片描述

  4. 为什么使用redis作为缓存
    在这里插入图片描述

  5. Redis高性能高并发的原因

     (1)基于内存的存储:Redis将数据存储在内存中,相对于磁盘存储来说,内存访问速度更快。这使得Redis能够快速读取和写入数据,
     	从而实现高性能。
     (2)单线程模型:Redis采用了单线程模型,即每个Redis实例都由一个主线程来处理所有请求。虽然看起来似乎不会支持高并发,但实际上,
     	这种单线程模型通过异步非阻塞的方式处理多个客户端请求,从而避免了线程切换的开销。这使得Redis能够有效地处理大量并发请求。
     (3)事件驱动:Redis使用事件驱动的方式来处理客户端请求,它依赖于事件循环(event loop)来监听和处理事件。
     	这种事件驱动的机制允许Redis在一个线程中高效地处理多个客户端连接,而无需创建大量线程,从而减少了线程管理的开销。
     (4)非阻塞IO操作:Redis使用非阻塞IO操作,这意味着它可以在等待IO完成的同时继续处理其他请求,而不会被阻塞。
     	这对于高并发场景非常重要,因为它允许Redis在处理多个客户端请求时保持高响应性。
     (5)高效的数据结构:Redis内置了许多高效的数据结构,如哈希表、跳跃表和位图,
     	这些数据结构在不同场景下提供了高性能的数据操作。
     (6)持久性选项:尽管Redis主要是一个内存数据库,但它提供了多种持久性选项,可以将数据定期保存到磁盘上。
     	这可以确保即使在服务器重启时,数据也不会丢失,同时不会牺牲太多性能。
     (7)集群和复制:Redis支持主从复制和集群模式,这可以通过多个Redis实例来提高性能和可用性。
     	主从复制可以将负载分散到多个节点上,而集群模式可以水平扩展以应对更多的并发请求。
     (8)优化的网络协议:Redis使用自己的高效二进制协议,该协议具有较低的开销,可以在网络上传输更少的数据,从而提高了网络性能。
    
  6. IO多路复用
    在这里插入图片描述
    在这里插入图片描述
    IO多路复用-select方式:
    在这里插入图片描述
    内核数据准备好或者超时后会将数据拷贝到用户空间,然后用户空间遍历fd_set,找到就绪的fd,读取其中的数据
    在这里插入图片描述
    IO多路复用-poll方式:

在这里插入图片描述
IO多路复用-epoll方式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
信号趋动IO
在这里插入图片描述

  1. Redis中的IO(网络模型IO多路复用)
    前提:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    以一个基于epoll的web服务为例理解redis中网络模型对应的api

    在这里插入图片描述

    在这里插入图片描述

  2. redis mysql区别(从处理业务的角度回答)
    在这里插入图片描述

  3. Redis setnx分布式锁

     (1)获取锁:
     	key:自定义前缀+参数name,name为模块名+用户ID,可以实现对同一用户加锁
     	value: UUID+当前线程ID
     	设置过期时间
     (2)释放锁:
     	lua脚本:根据value判断是否是自己的锁,然后del key删除锁
     (3)自动续期:
     	在获取到锁的同时,启动一个定时任务或者后台线程,定时使用 Lua 脚本更新锁的过期时间。
     	Lua 脚本可以通过比较当前锁的值是否与之前设置的唯一标识符相同来确保只有持有锁的客户端可以进行续期操作。
     	续期时间应该小于锁的过期时间,以确保在客户端因故障或其他原因导致无法续期时,锁能够最终过期释放。
     (4)注意
     	锁的过期时间需要根据业务操作的预估时间和系统负载来设置,避免锁的过期时间过短或过长。
     	续期操作需要保证原子性,可以使用 Lua 脚本将获取锁和续期操作原子化执行。
     	锁的持有时间应该有一个上限,避免因为某个客户端发生故障而导致锁无法被释放。
     	客户端在获取锁前,可以设定一个尝试获取锁的超时时间,避免长时间的等待。
    
  4. 守护线程可以续期(如何实现),当过期时间为10,守护线程在9时进行续期,但是如果此时发生gc,出现stw,此时续期会失败。该如何解决。
    在这里插入图片描述

  5. Redission原理
    链接

    ​以上使用setnx实现分布式锁步骤考虑到了使用分布式锁需要考虑的互斥性、防死锁、加锁和解锁必须为同一个进程等问题,
    但是锁的续期无法实现。所以通常情况都是采用 Redisson 实现 Redis 的分布式锁,
    借助Redisson的 WatchDog机制能够很好的解决锁续期的问题。
    Watch Dog 机制其实就是一个后台定时任务线程,获取锁成功之后,会将持有锁的线程放入到一个 RedissonLock.EXPIRATION_RENEWAL_MAP里面,
    EXPIRATION_RENEWAL_MAP中的key为锁名,value为uudId+线程id;
    然后每隔 10 秒 (internalLockLeaseTime / 3)定时执行一次定时任务 -->检查一下,如果客户端 1 还持有锁 key.
    判断客户端是否还持有 key,其实就是遍历 EXPIRATION_RENEWAL_MAP 里面线程 id 然后根据线程 id 去 Redis 中查,如果存在就会延长 key 的时间,
    那么就会不断的延长锁 key 的生存时间。
    
  6. 缓存雪崩
    链接描述

项目

  1. 实习遇到的问题
  2. 两个项目上线了吗,单独完成还是合作
  3. 项目redis各种数据结构使用场景
  4. 项目中三方库替换后,如果后续又超期再次替换是否还会很麻烦:
    不会:本次替换已经将所有涉及api封装到工具类,下次直接修改该脚本
  5. 项目中用到了es,了解的底层原理吗
    只了解倒排索引
  6. 介绍一下实习项目,以及负责的excel上传下载接口的逻辑
  7. 你们项目中如果程序出错了怎么处理的
    用户导致的:抛出错误提示。
    系统内部:回滚
  8. 项目中的工作量(安全连线、三方库替换)
  9. 三方库替换将设计函数封装为utils,java中那些场景需要封装工具类
  10. 例如:string相关的操作需要封装工具类吗
  11. 封装工具类仅仅是为了维护和修改方便吗,有其他原因吗
  12. 项目遇到的困难
  13. Python、Java的掌握程度、学习时间及方式

分布式

  1. 异步业务:类似于购物下单,异步处理如果失败了怎么办
    重试+死信队列(你这个思路业务太复杂,不好实现)
    (1)业务逻辑有问题,无法执行成功
    (2)依赖的第三方服务有问题:例如mysql宕机了,暂时无法执行
    在这里插入图片描述

  2. 访问量过高,系统如何设计(高可用)
    高可用设计
    集群、限流(令牌桶)、熔断、降级、超时重试、异步调用
    在这里插入图片描述
    在这里插入图片描述

  3. 分布式事务理论
    CAP

    CAP 也就是 Consistency (一致性) 、Availability (可用性) 、Partition Tolerance(分区容错性) 这三个单词首字母组合。
    一致性 (Consistence) :所有节点访问同一份最新的数据副本
    可用性 (Availability):非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)。
    分区容错性 (Partition tolerance) : 分布式系统出现网络分区的时候,仍然能够对外提供服务。
    

    网络分区:分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题) 某些节点之间不连通了,整个网络就分成了几块区域,这就叫网络分区。

    当发生网络分区的时候,如果我们要继续服务,那么强一致性和可用性只能 2 选1。
    也就是说当网络分区之后 P 是前提,决定了 P 之后才有 C 和 A 的选择。
    也就是说分区容错性 (Partition tolerance) 我们是必须要实现的。
    简而言之就是: CAP 理论中分区容错性 P 是一定要满足的,在此基础上,只能满足可用性 A 或者一致性 C。
    为啥无同时保证 CA 呢?
    举个例子: 若系统出现“分区”,系统中的某个节点在进行写操作。为了保证 C, 必须要禁止其他节点的读写操作,这就和 A 发生冲突了。
    如果为了保证 A,其他节点的读写操作正常的话,那就和 C 发生冲突了。
    选择的关键在于当前的业务场景,没有定论,比如对于需要确保强一致性的场景如银行般会选择保证 CP 。
    

    BASE

    BASE 是 Basically Available (基本可用) 、Soft-state (软状态) 和 EventuallyConsistent (最终一致性) 三个短语的缩写。
    BASE 理论是对 CAP 中一致性 C 和可用性A 权衡的结果,其来源于对大规模互联网系统分布式实践的总结,
    是基于 CAP 定理逐步演化而来的,它大大降低了我们对系统的要求。
    核心思想:也就是牺牲数据的强一致性来满足系统的高可用性,系统中一部分数据不可用或者不一致时,仍需要保持系统整体“主要可用”
    

    在这里插入图片描述
    分布式一致性的 3 种级别:

    1.强一致性 : 系统写入了什么,读出来的就是什么
    2.弱一致性 : 不一定可以读取到最新写入的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态。
    3.最终一致性:弱一致性的升级版。,系统会保证在一定时间内达到数据一致的状态,
    业界比较推崇是最终一致性级别,但是某些对数据一致要求十分严格的场景比如银行转账还是要保证强一致性。
    
  4. 分布式事务实现方式
    链接

  5. 分布式事务场景:向mysql和mq写入数据
    本地消息表实现:
    (1)使用消息表记录需要写入mq的消息记录,信息写入mysql。(同一个事务执行)
    (2)使用后台程序源源不断的扫描消息表中的记录并写入mq,若写入成功则删除对应消息

  6. 1000万条数据,找出出现次数最多的前100条数据(内存有限)

    外部排序内次取10万条放入内存,找出前100条数据,然后归并
    存在问题:某个数据并不是在前100,但是由于其分散不均匀,导致其在某块中位于前100,这种情况该如何解决。
    在这里插入图片描述

  7. 0-68包含2,或7数字的个数

     有规律,可以写出递推公式吗?(听她讲了好久还是没明白)
     假设范围内的最大数字有n位,则从最高位开始计算,f(n)表示第n位为2,7的数字个数。
     则f(n) = x * 10 ^(n-1),其中x是判断第n位的数可以取2,7的数字个数。
     所以解答的核心是如何确定x:
     (1)针对于最高位,要防止越上界,最高位为6,只能包含2,所以x=1
     (2)针对于最低为,要防止越上界,最低为为8,可以包含2,7,所以x=2
     (3)针对于中间位,x值为题目要求包含的数字个数。Eg:2,7都可以,所以为2
     以6为例,只包含2所以x=1。最高位和最低位的x要分开处理,中间位置的x取值均为2(要求包含数字的个数)
     以0-68为例, n = 2;
     F(2) = 1 * 10^1
     F(1)= 2 * 10^0
     最终将f(0) + ... + f(n)求和即可。
     以0-100为例,求包含2或7数字的个数
     F(3) = 0 * 10 ^2
     F(2) = 2 * 10 ^ 1
     F(3) = 0 * 10 ^ 0
     最终结果为20个数字即(2,12,...92和20,21,...29)
    
  8. 20个服务节点,结点有输入输出均为list,某个节点的输出list中的某个值可能是其他节点的输入,如何能快速执行完20个结点。
    拓扑图。如何构建拓扑图是一个问题
    面试官:可以用空间换时间,一直在问空时复杂度

  9. MQ的设计模式

     (1)发布-订阅模式(Publish-Subscribe Pattern):
     	描述:发布-订阅模式允许一个消息发布者将消息发送到多个订阅者,而不需要订阅者知道消息来自哪个发布者。
     	用例:用于实现广播消息,例如新闻订阅、实时通知等。
     	实现:通常通过主题(Topic)或交换机(Exchange)来实现,发布者将消息发布到特定主题,
     	订阅者订阅感兴趣的主题。
     (2)点对点模式(Point-to-Point Pattern):
     	描述:点对点模式中,消息从一个发送者传递到一个接收者,每个消息只能被一个接收者消费。
     	用例:用于实现任务队列,例如工作排队、负载均衡等。
     	实现:通常通过队列(Queue)来实现,消息被发送到队列,接收者从队列中获取消息。
     (3)请求-响应模式(Request-Reply Pattern):
     	描述:请求-响应模式允许客户端发送请求消息并等待服务器响应消息,通常用于同步通信。
     	用例:用于RPC(远程过程调用)或需要精确响应时间的场景。
     	实现:客户端发送请求消息到队列或主题,服务器接收请求并发送响应消息。
     (4)消息过滤模式(Message Filter Pattern):
     	描述:消息过滤模式允许订阅者根据特定条件过滤消息,只接收满足条件的消息。
     	用例:用于筛选感兴趣的消息,减少不必要的消息传递。
     	实现:订阅者可以定义消息过滤条件,MQ将消息传递给满足条件的订阅者。
     (5)消息重试模式(Message Retry Pattern):
     	描述:消息重试模式允许在消息传递失败时进行重试,以确保消息被成功处理。
     	用例:用于处理失败恢复或消息可靠性要求高的场景。
     	实现:通常通过设定重试策略、延迟重试或死信队列来实现。
     (6)消息确认模式(Message Acknowledgment Pattern):
     	描述:消息确认模式允许消费者发送确认消息,告知MQ消息已经被成功处理。
     	用例:用于确保消息不会被重复处理。
     	实现:通常有手动确认和自动确认两种方式,消费者发送确认消息以确认消息处理完成。
    
  10. Mq的使用场景
    异步任务,eg:下单、分布式事务

  11. 下单的完整流程(包含付款,判断库存、异步等操作的前后顺序

     (1)下单请求:
     	客户端发起下单请求,将订单信息发送到服务器。
     (2)库存检查:
     	服务器接收到下单请求后,首先进行库存检查,确保所需商品的库存足够。
     	并把用户欲购买的商品锁定,设定一个锁定时间,锁定时间内没有付款则释放库存。
     	如果库存不足,服务器发送一条库存不足的通知给客户端,客户端可以选择修改订单或者取消订单。
     (3)付款处理:
     	如果库存检查通过,服务器将订单信息发送给付款系统进行付款处理。这可以是同步或异步的过程,具体取决于付款系统的设计和性能要求。
     	付款系统处理付款请求,返回付款结果。
     (4)订单创建:
     	服务器接收到付款结果后,将订单信息保存到数据库中,创建订单。
     	订单创建成功后,服务器生成订单号等相关信息。
     (5)通知客户下单成功
     (6)异步处理其他操作:
     	除了上述基本流程,可能还有其他后续操作,如发货、通知物流、发送发票等。这些操作通常是异步的,可以通过消息队列来处理。
     	服务器将这些操作封装成消息,发送到相应的消息队列,等待后续处理。
     (7)后续处理:
     	后续处理可以由独立的服务或者工作者来完成。这些工作者从消息队列中接收消息,执行相应的操作。
     	例如,发货工作者会从消息队列中接收到需要发货的订单信息,然后进行发货操作。
     	这些后续操作可以并行执行,提高了系统的性能和可伸缩性。
     (8)通知客户端:
     	在完成后续操作后,服务器可以发送通知给客户端,告知订单的状态更新,如发货通知、物流跟踪信息等。
    
  12. 大数据了解吗?Eg:分库分表
    链接描述

  13. redis mysql数据一致性
    延迟双删(小林coding)
    canal保证一致性

框架

  1. Spring 和springboot区别,springboot特点

  2. ioc aop

  3. 循环依赖问题

    循环依赖就是A依赖B,而B又依赖A,Spring是怎么做的?

     其实也是在Spring的生命周期里面,从Spring的生命周期可以知道,对象属性的注入在对象实例化之后的。它的大致过程是这样的:
     (1)首先A对象实例化,然后对属性进行注入,发现依赖B对象;
     (2)此时B对象还没有创建出来,所有转头去实例化B对象
     (3)B对象实例化之后,发现需要依赖A对象,那A对象已经实例化了,所以B对象最终能完成创建
     (4)B对象返回到A对象的属性注入的方法上,A对象最终完成创建
     原理:三级的缓存,三级缓存其实就是三个Map
     singletonObjects(一级,日常实际获取Bean的地方)
     earlySingletonObjects(二级,还没进行属性注入,由三级缓存放进来)
     singletonFactories(用于保存bean创建工厂,以便于后面扩展有机会创建代理对象)
    

    在这里插入图片描述

  • A对象实例化之后,属性注入之前,其实会把A对象通过addSingletonFactory()放入三级缓存中,key是beanName,value是singletonFactories(ObjectFactory)。

  • 等到A对象属性注入(setter 方法属性注入)时,发现依赖B,那么他就会从三级缓存中的第一级缓存开始依次查找有没有B对应的Bean,肯定都没有啊,因为B还没创建呢,又去实例化B。

  • B就开始创建了,先实例化一个B对象,然后缓存对应的一个singletonFactories到第三级缓存中,然后就到了需要处理属性注入,即B属性注入需要去获取A对象,这里就是从三级缓存中的第一级缓存开始依次查找有没有A对应的Bean,结果从三级缓存里拿出singletonFactories,调用其getObject得到对应的实例化但未初始化的Bean(不完整对象A的引用)。

  • 然后将早期的A对象放到二级缓存,删除三级缓存中的A。为什么需要放到二级缓存,主要是怕还有其他的循环依赖,如果还有的话,直接从二级缓存中就能拿到早期的A对象(保证对象的一致性)。(等到bean完全初始化之后,就会把二级缓存给remove掉,塞到一级缓存中)。

  • 于是接下来就把早期的A对象注入给B,此时B的属性注入A对象就完成了,之后再经过其他阶段的处理之后,B对象就完完全全的创建完了。

  • B对象创建完之后,就会将B放入第一级缓存,然后清空B对应的第三级缓存,当然也会去清空第二级缓存,只是没有而已,至于为什么清空,很简单,因为B已经完全创建好了,如果需要B那就在第一级缓存中就能查找到,不需要在从第二级或者第三级缓存中找到早期的B对象。

  • B对象完完全全的创建完之后。然后A就会跟B一样,继续处理其它阶段的,完全创建好之后,也会清空二三级缓存,放入第一级缓存。

  • B在构建的时候,已经注入了A的引用,虽然是早期的A,但的确是A对象,现在又把B注入给了A,那么是不是已经解决了循环依赖的问题了,A和B都各自注入了对方,如图。上面的A是A单例对象的引用,所以还是符合单例模式
    在这里插入图片描述

      主要是第二级和第三级用来存早期的对象,这样在有循环依赖的对象,就可以注入另一个对象的早期状态(引用),
      从而达到解决循环依赖的问题,由于是同一个引用,所以,早期状态的对象在构建完成之后,也就会成为完完全全可用的对象。
      总结:上面解决的循环依赖其实是属性注入时的循环依赖,即setter 方法的注入。
      Spring中的属性注入的方式:
      (1)setter注入
      (2)构造方法注入
      (3)基于注解的注入
      如果是构造器的注入,spring则不能解决,因为对于构造器的循环依赖来说,在 bean 调用构造器实例化之前(bean生命周期的实例化),
      bean还没有实例化,所以一二三级缓存并没有 bean 的任何相关信息,在实例化之后才放入三级缓存中,
      因此当 getBean 的时候缓存并没有命中,这样就抛出了循环依赖的异常了。所以spring不能解决构造器的循环依赖
      问题:
    

    问题1: 如果只有一级缓存可以解决循环依赖吗(一级缓存放的是完整bean)

      实例化A对象。填充A的属性阶段时需要去填充B对象,而此时B对象还没有创建,所以这里为了完成A的填充就必须要先去创建B对象;
      实例化B对象。执行到B对象的填充属性阶段,又会需要去获取A对象,而此时Map中没有A,因为A还没有创建完成,导致又需要去创建A对象。
      这样,就会循环往复,一直创建下去,只到堆栈溢出。
      为什么不能在实例化A之后就放入Map?
      因为此时A尚未创建完整,所有属性都是默认值,并不是一个完整的对象,在执行业务时可能会抛出未知的异常。
      所以必须要在A创建完成之后才能放入Map。
    

    问题2:如果只有一二级缓存

      此时我们引入二级缓存用另外一个Map2 {k:name; v:earlybean} 来存储已经开始创建但是尚未完整创建的对象。
      1.实例化A对象之后,将A对象放入Map2中。
      2.在填充A的属性阶段需要去填充B对象,而此时B对象还没有创建,所以这里为了完成A的填充就必须要先去创建B对象。
      3.创建B对象的过程中,实例化B对象之后,将B对象放入Map2中。
      4.执行到B对象填充属性阶段,又会需要去获取A对象,而此时Map中没有A,因为A还没有创建完成,
      但是我们继续从Map2中拿到尚未创建完毕的A的引用赋值给a字段。这样B对象其实就已经创建完整了,尽管B.a对象是一个还未创建完成的对象。
      5.此时将B放入Map并且从Map2中删除。
      6.这时候B创建完成,A继续执行b的属性填充可以拿到B对象,这样A也完成了创建。
      7.此时将A对象放入Map并从Map2中删除。
      8.B中提前注入了一个没有经过初始化的A类型对象不会有问题吗?
      虽然在创建B时会提前给B注入了一个还未初始化的A对象,但是在创建A的流程中一直使用的是注入到B中的A对象的引用,
      之后会根据这个引用对A进行初始化,所以这是没有问题的。
    

    问题3:二级缓存已然解决了循环依赖问题,为什么还需要三级缓存?

      只要两个缓存确实可以做到解决循环依赖的问题,但是有一个前提这个bean没被AOP进行切面代理,如果这个bean被AOP进行了切面代理,
      那么只使用两个缓存是无法解决问题,因为一二级缓存中存放的都是原始对象,而我们需要注入的其实是A的代理对象。
    

    问题4:为什么不能只使用一级+三级缓存

      如上一个问题所述,如果出现循环依赖+aop时,属性注入的就是代理对象,但是,三级缓存有一个硬性要求:
      多个地方注入这个动态代理对象需要保证都是同一个对象,如果多个对象依赖了A,
      则它们在三级缓存中的取出来的A的动态代理对象每次都是由工厂创建的新对象,地址值不一样。
      所以需要一个二级缓存来存,保证代理对象的一致性,如果二级里面有就不用查三级了。
    
  1. Mvc原理
    在这里插入图片描述
    流程说明
    (1) 客户端(浏览器)发送请求, DispatcherServlet拦截请求。
    (2) DispatcherServlet 根据请求信息调用 HandlerMapping 。HandlerMapping 根据 URL 去匹配查找能处理的 Handler(也就是我们平常说的 Controller 控制器) ,并会将请求涉及到的拦截器和 Handler 一起封装。
    (3) DispatcherServlet 调用 HandlerAdapter适配器执行 Handler 。
    (4) Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给DispatcherServlet,ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。Model 是返回的数据对象,View 是个逻辑上的 View。
    (5) ViewResolver 会根据逻辑 View 查找实际的 View
    (6) DispaterServlet 把返回的
    Model 传给 View(视图渲染)。
    (7) 把 View 返回给请求者(浏览器)

  2. 自动装配
    链接描述

  3. springboot 相较于spring的优点

    在这里插入图片描述

  4. Spring @transaction事务实现原理(相对于AOP更底层的原理)

    链接描述

  5. 事务失效的情况
    链接描述

java

15.Java对象和spring bean的区别
16.Java创建对象的流程
17.有遇到过内存溢出的情况吗:栈溢出、堆溢出。
18.堆溢出的原因,什么时候进行gc
19.Arraylist get put
1. Java和python的区别
2. Java代码一次编译,可以随时运行的原理
3. Int和Integer的区别

(1)数据类型:
	int 是一种基本数据类型(primitive data type)
	Integer 是一个类,通常被称为包装类(wrapper class)。
(2)可空性:
	int 是一个原始数据类型,不能表示为 null,即它不具备可空性。如果不初始化,它将有一个默认值,如 0。
	Integer 是一个对象,可以具备可空性。它可以被设置为 null,表示没有值。
(3)自动装箱和拆箱:
	在Java等支持自动装箱和拆箱的语言中,可以将 int 自动转换为 Integer 和反之,
	这种过程称为自动装箱(autoboxing)和自动拆箱(unboxing)。
(4)可空性、泛型、集合等都需要Integer

4. Arraylist和linkedlist区别
5. 线程池设计
在这里插入图片描述
根据题目要求:1s内可以执行两个任务,所以核心线程数设置为100,最大线程数可以设置为200
4. Hashmap扩容

网络

8.Tcp和udp区别
9.Udp场景
10.聊天框使用那种协议,具体到应用层

(1)WebSocket:WebSocket 是一种全双工通信协议,通常用于实时聊天应用程序。它建立在 TCP 协议之上,允许客户端和服务器之间双向通信,
从而实现实时消息传输。WebSocket 在现代Web应用中广泛使用,因为它提供了低延迟和高效的实时通信。
(2)HTTP(Hypertext Transfer Protocol):虽然 HTTP 主要用于 Web 页面的请求和响应,但也可以用于长轮询(long polling)
和 Server-Sent Events(SSE)等技术来实现实时消息传输。然而,相对于WebSocket,HTTP在实时聊天中的性能和效率通常较低。

13.学习技术的途径

数据结构

  1. 栈和队列应用场景
    在这里插入图片描述

  2. 字典树
    在这里插入图片描述
    在这里插入图片描述
    对于字典树(Trie树)的节点,一般情况下是不直接存放字符码的。通常,在字典树的节点中,会存储一个指向子节点的指针数组或哈希表,每个指针指向一个子节点。这样可以根据字符串的字符在字母表中的位置来索引对应的子节点。

设计模式

  1. 单例模式
    反序列化破坏单例的原因及解决方案

HR

7.职业规划

手撕

20.合并两个有序数组
4.算法题:java实现输出字符串中第一个出现不重复的字符详解
没有通过全部测试用例(答案:队列+map)

18.k个一组反转链表

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

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

相关文章

【Java 进阶篇】数据定义语言(DDL)详解

数据定义语言(DDL)是SQL(结构化查询语言)的一部分,它用于定义、管理和控制数据库的结构和元素。DDL允许数据库管理员、开发人员和其他用户创建、修改和删除数据库对象,如表、索引、视图等。在本文中&#x…

【C++杂货店】类和对象(上)

【C杂货店】类和对象(上) 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…

【Spring Cloud】认识微服务架构,拆分简单的 Demo 实现服务的远程调用

文章目录 前言一、认识微服务1.1 服务架构的演变:从单体到微服务单体架构分布式架构微服务架构 1.2 微服务技术的对比:Dubbo、Spring Cloud、Spring Cloud Alibaba技术对比公司需求的选择 1.3 Spring Cloud:微服务框架的精华什么是 Spring Cl…

【Vue.js】使用ElementUI实现增删改查(CRUD)及表单验证

前言: 本文根据上篇实现数据表格(查所有)完善增删改功能,数据表格》查看数据表格的实现链接 一,增删改查 ①后端Controller(增删改查方法): package com.zking.ssm.controller;import com.zking.ssm.model.Book; import com.z…

新能源汽车行业出口ERP管理解决方案

中国汽车企业以史无前例的规模进军慕尼黑车展。本届展会,中国汽车参展企业数量达50家,是2021年的两倍。欧洲销售的新型电动汽车中,8%由中国品牌制造。2022年上半年,中国电动汽车的平均价格不到3.2万欧元(3.5万美元&…

香港云服务器和日本云服务器哪个好?(详细对比)

​  购置海外服务器时,您是在乎网络速度?价格?稳定性?当这几个因素同时存在,我们该如何选择?本篇针对海外热门的两个地区,中国香港和日本,这两种云服务器谁优谁劣?各有什么亮点?逐一进行对比分析。 一、速度上来看 中国香…

Tungsten Fabric数据量过大问题处理初探

开源SDN系统Tungsten Fabric面临数据产生过多问题。 经排查,产生数据多出自analytics组件的Cassandra数据库()。很多分析数据会存储至Cassandra库,并持久化处理。 没有特殊调整的话,目录在 /var/lib/docker/volumes/analytics_database_an…

春招秋招,大学生求职容易遇到哪些问题?

每到毕业季就有大批大学生从校园出来,他们怀抱梦想,希望能做出一番成绩。但现实总归是残酷的,有些人找不到工作,有一些人频繁跳槽,也有一些人最终找到的工作与自己的专业没有一点关系,迷茫好几年才找到方向…

数字音频工作站FL Studio 21中文版下载及电音编曲要用乐理吗 电音编曲步骤

FL Studio 21是一款强大的数字音频工作站(DAW)软件,为您提供一个完整的软件音乐制作环境。它是制作高质量的音乐、乐器、录音等的完整解决方案。该程序配备了各种工具和插件,帮助你创建专业的虚拟乐器,如贝斯、吉他、钢…

探索Moonbeam路由流动性的强大功能

Moonbeam的GMP预编译作为MRL的接口,有助于将带有Token的消息从GMP协议(通过XCMP)传输到与Moonbeam链接的平行链。 为何是个重磅消息?因为这项技术使得将流动性从外部区块链转移到其他波卡平行链成为可能! 这里补充一…

快手商品详情数据接口

快手商品详情数据接口的调用需要使用快手提供的API接口。API接口是一种程序之间进行交互的方式,它允许两个程序或者网页之间互相通信、交换数据。 快手API接口的具体使用方法和步骤需要您参考快手的官方文档或者开发者指南。在使用快手API接口时,您需要…

基于遗传算法解决的多仓库多旅行推销员问题(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

【Python基础】if __name__ == ‘__main__‘:和assert函数

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…

day49 jdbc技术

一、概述 什么是JDBC Java DataBase COnnectivity Java 数据库连接 其实就是利用Java程序连接并访问数据库的一种技术 为什么要学习JDBC 之前我们是通过终端,或者第三方工具直接连接数据库 在企业开发中,更多的是通过程序来连接数据库的 未来学习的M…

docker部署MinIO集群

docker部署MinIO集群 1 拉取镜像 docker pull minio/minio:RELEASE.2023-08-16T20-17-30Z 2 启动集群节点命令 注意:要对配置文件中使用到的文件夹进行授权 version: 3 # 公共操作 x-minio-common: &minio-commonimage: minio/minio:RELEASE.2023-08-16T20-17…

SpringCloud nacos1.x.x版本升级到2.2.3版本并开启鉴权踩坑

近期由于服务器漏洞扫描,检测出nacos存在绕过登录鉴权漏洞,如图 需要进行升级并开启鉴权,就此次升级做下记录。 1.首先备份原来的nacos,导出配置文件作为备份; 2,从官网下载nacos-server-2.2.3.zip&#x…

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过 Docker 容器化技术在华为云云耀云服务器快速构建网站

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过 Docker 容器化技术在华为云云耀云服务器快速构建网站 介绍华为云云耀云服务器 华为云云耀云服务器 (目前已经全新升级为 华为云云耀云服务器L实例) 华为云云耀云服务器…

目标检测算法改进系列之Backbone替换为LSKNet

LSKNet Large Selective Kernel Network(LSKNet)可以动态地调整其大空间感受野,以更好地建模遥感场景中各种物体的测距的场景。据我们所知,这是首次在遥感物体检测领域探索大选择性卷积核机制的工作。在没有任何附加条件的情况下…

zemaxRKE广角目镜

在埃尔弗目镜的基础上,用一个消色差双胶合透镜取代了原本的双凸单透镜 半视场增加到35度 色差矫正很好 成本较低、生产工艺成熟 入瞳直径4mm波长0.51、0.56、0.61半视场35焦距28mm 镜头参数 效果: 成像光路: