JVM1.那有哪些对象是可以直接在栈上分配呢?在Java中,并不是特定类型的对象能够直接在栈上分配,而是取决于该对象的作用域。JVM通过一种叫做“逃逸分析”(Escape Analysis)的技术来判断一个对象是否可以安全地在栈上分配。
如果一个对象的引用没有“逃逸”出它被创建的方法之外,那么它就可能被优化为在栈上分配。这样做的好处是,当方法执行结束时,栈帧被弹出,对象的内存会立即被回收,无需等待垃圾回收(GC),从而提高性能。
逃逸分析是JIT(即时编译器)的一项优化技术,默认在现代JVM中是开启的。只有那些生命周期完全局限于单个方法调用内、体积较小且线程安全的对象,才最有可能被优化到栈上进行分配。
未逃逸的定义:
仅在方法内部使用:对象的引用完全封装在方法体内,没有被方法返回。
未赋值给外部变量:没有将该对象的引用赋值给任何类变量(static字段)或实例变量。
未传递给可能逃逸的方法:没有将该对象的引用作为参数传递给其他方法,或者传递给了但能确定其他方法也不会让它“逃逸”。
逃逸的例子:
比如对象作为方法的返回值,他就是逃离了这个方法的作用域
对象引用赋值给实例变量,也是 ...
Redis1.多级缓存数据一致性与失败回滚当被问及如何保证Redis和本地缓存更新的原子性,以及在更新失败时如何回滚,你的回答提到了不甚准确的“编程式事务”,并最终倾向于人工处理。
方案1:引入消息队列(MQ)进行可靠的异步处理
修改架构:Canal不再直接调用消费逻辑,而是将解析后的binlog事件作为消息发送到MQ的一个Topic中。
消费者逻辑:消费者服务从MQ拉取消息。其处理逻辑是:先失效Redis缓存,再发布一个广播消息(如通过Redis Pub/Sub)通知所有应用实例失效本地Caffeine缓存。
失败处理:只有当所有步骤成功后,消费者才向MQ发送ACK。如果处理过程中任何一步失败(如Redis连接超时),消费者不发送ACK。MQ会在超时后将该消息重新投递给其他消费者,实现自动重试。
方案2 死信队列
在Canal的消费者逻辑中,使用Spring Retry等框架对缓存失效操作进行封装。
配置重试策略,例如重试3次,每次间隔采用指数退避(如1s, 2s, 4s),避免在故障期间频繁冲击下游服务。
配置一个RecoveryCallback。当所有重试都失败后,将这条失 ...
SpringCloudNacos1.Nacos动态配置刷新的原理是什么?核心机制: 长轮询(Long Polling)。
客户端行为: 应用启动后,客户端向Nacos Server请求配置,并建立一个长轮询连接,询问配置是否有更新。
服务端行为: 如果配置无变更,服务端会hold住请求30秒(默认);如果期间配置发生变更,立即响应;如果超时,也返回一个空响应。
刷新流程: 客户端收到变更响应后,拉取最新配置,发布EnvironmentChangeEvent事件。
Spring侧响应: @RefreshScope注解的Bean监听到事件后,会销毁并重新创建,从而加载到新配置。
2.Nacos 1.x 和 2.x 有什么核心区别?通信模型升级: 最大的变化是从HTTP短连接轮询模型升级为gRPC长连接模型。
性能提升: gRPC基于HTTP/2,使用长连接和二进制协议,大大降低了通信开销和服务器压力,服务注册/发现和配置推送的性能提升了一个数量级。
推送机制: 从1.x的UDP推送通知+HTTP拉取数据,变为2.x的gRPC直接推送数据,实时性更强,更可靠。
架构演进: 2.x引入了统一的 ...
设计模式1.当被问及如何在多个接口中统一管理以避免代码重复时你的初步想法是提取一个公共方法。面试官进一步引导你思考过滤器和拦截器。
方案1:使用Spring MVC的HandlerInterceptor(拦截器)
HandlerInterceptor是Spring MVC提供的AOP实现,专门用于在Controller方法执行前后进行预处理和后处理。它与请求生命周期紧密耦合,是处理用户认证、日志记录、上下文设置等横切关注点的标准方式。
创建一个类实现HandlerInterceptor接口。
在preHandle方法中,从请求(如Header)中获取Token,解析出用户信息,然后调用工具类的set()方法将用户信息存入ThreadLocal。
在afterCompletion方法中,无论Controller方法执行成功还是失败,都调用工具类的remove()方法清理ThreadLocal,通常放在finally块中以确保执行。
创建一个配置类实现WebMvcConfigurer,重写addInterceptors方法,将你的拦截器注册到Spring容器中,并配置其拦截路径(如/ap ...
Spring框架1.SpringBoot的配置加载优先级首先我们先确定一下配置加载优先级是按照我以下的顺序,由高到低的。分别是:
先是命令行参数(--server.port=9000 或 java -jar app.jar --spring.config.location=...)
然后是我们的系统的环境变量和JVM系统属性,比如设置端口为8080,比如我们在这里设置API的KEY
然后RandomValuePropertySource(random.* 占位符,用于生成随机数/字符串,可在配置中引用)
接着是外部配置文件(properties / yml)
JAR 包外部的 ./config/
JAR 包外部的 ./
JAR 包内部的 classpath:/config/
JAR 包内部的 classpath:/
接着是我们@PropertySource注解指定的配置
最后是我们Springboot默认的配置
然后在配置文件中,properties的配置大于yml,因为springboot是按加载顺序来的,后加载的properties把yml的值给覆盖了
...
Mysql1.多表join的时候,小表驱动大表在Mysql的 Nested Loop Join 中
驱动表(outer table):首先被扫描的表。
被驱动表(inner table):对驱动表每一行,根据 Join 条件去查找匹配行的表。
核心原则:过滤后剩余行数少的表,应该作为驱动表,这样可以减少被驱动表的访问次数。这就是小表
执行过程:
扫描驱动表(全表扫描或索引扫描)。
对驱动表的每一行,根据连接条件在被驱动表中查找(通常用索引 B+Tree 查找)。
如果被驱动表使用二级索引且需要回表,则访问主键索引。
小表驱动大表,大表负责命中索引。
比如
1select * from A straight_join B on A.a = B.a;
数据库会全表扫A,然后每拿到一行就去比较条件 A.a=B.a,去B表里面查,B表命中索引的查询。实际上就是一个搜索树,查询的时间复杂度近似log2^B^,然后加上一次回表,可能就是2Log2 ^B^,所以总体的时间复杂度为A+2log2^B^*A,如果是覆盖索引的话,复杂度可降为 O(A + log₂(B) × A)
所以我的们A越小越好,j ...
基础字段基础标识符和关键字Go语言中有25个关键字:
12345break default func interface selectcase defer go map structchan else goto package switchconst fallthrough if range typecontinue for import return var
此外,Go语言中还有37个保留字。
12345678910Constants: true false iota nil Types: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr ...
NacosNacos致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
服务发现RestTemplate服务调用:
在定义RestTemplate的时候,增加了@LoadBalanced注解,而在真正调用服务接口的时候,直接采用服务名的时候来写请求路径即可。在真正调用的时候,Spring Cloud会将请求拦截下来,然后通过负载均衡器选出节点,并替换服务名部分为具体的ip和端口,从而实现基于服务名的负载均衡调用。
Feign服务调用:
主要先通过@EnableFeignClients注解开启扫描Spring Cloud Feign客户端的功能;然后又创建一个Feign的客户端接口定义。使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就可以来绑定服务提供方的REST接口,比如下面就是绑定 ...
入门核心概念
节点 (Node): 代表实体,就像关系型数据库中的一行数据。例如:一个人、一部电影、一个公司。节点可以有标签 (Label) 来分类,比如 :Person, :Movie。
关系 (Relationship): 代表节点之间的连接,这是图数据库的精髓。例如:[:ACTED_IN] (出演), [:DIRECTED] (导演)。关系必须有方向和类型。
属性 (Property): 节点和关系都可以有属性,用来存储键值对数据。例如:一个 :Person 节点可以有 name: 'Keanu Reeves' 属性。
语句:
MERGE: 一个非常强大的命令,可以理解为 “匹配或创建”。如果节点/关系已存在,就匹配它;如果不存在,就创建它。常用来避免创建重复数据。
WHERE: 过滤条件,用法和 SQL 非常相似。
SET: 修改节点或关系的属性。
DELETE / DETACH DELETE: 删除节点和关系。DETACH DELETE 会在删除节点的同时,删除与它相连的所有关系。
可变长度路径: 查询两个节点之间任意长度的路径,例如 (a)-[*2 ...
Spring AI Alibaba Graph旨在利用 Spring AI 作为桥梁,连接阿里巴巴的大语言模型(如通义千wen)和图数据库(如阿里云 GDB),以实现通过自然语言与复杂关联数据进行交互的目的。
底层核心原理是 Text-to-Cypher/Gremlin,即将用户的自然语言问题,通过大语言模型(LLM)动态翻译成图数据库的专业查询语言。
设计思想图数据库(Graph Database)非常擅长处理实体之间的复杂关系,例如社交网络中的“朋友的朋友”、金融风控中的“资金链路”、电商中的“共同购买”等。但要查询这些数据,需要使用专门的图查询语言,如 Gremlin (阿里云 GDB 支持) 或 Cypher。这些语言学习门槛高,普通业务人员无法直接使用。
“Spring AI Alibaba Graph”架构的核心思想就是解决这个问题:让 LLM 充当一个智能的“翻译官”。
流程:
赋予 LLM 上下文知识 (Context Awareness):一个通用的 LLM 不知道你的图数据库里有什么。因此,必须在查询时,动态地告诉 LLM 图的“Schema”(模式),包括:
节 ...













