1. java检测文件编码
jchardet可以做
2. spring启动报错
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
就是需要一个bean,但是检测到两个。需要我们指定一个默认的,用@Primary。
3. 达梦8,order by不走索引解决
4. mysql explain sql后type几种类型
在MySQL中,EXPLAIN命令用于分析查询语句的执行计划。其中,type列是EXPLAIN结果中的一个重要字段,表示MySQL在执行查询时使用的访问方法。type字段描述了MySQL在访问表时的访问方式,也称为访问类型。
MySQL中常见的type类型有以下几种:
- ALL:表示全表扫描,即MySQL将遍历整个表来找到匹配的行。这是最慢的访问类型,应尽量避免。
- index:表示通过索引进行扫描,但需要扫描索引的全部或大部分。通常发生在使用非唯一索引的查询中。
- range:表示通过索引进行范围扫描,只扫描满足给定范围条件的行。例如,使用BETWEEN、IN、> <等条件查询。
- ref:表示使用非唯一索引或唯一索引的前缀来查找匹配的行。通常发生在多表连接查询中,通过索引来匹配关联条件。
- eq_ref:表示使用唯一索引来查找匹配的行。通常发生在多表连接查询中,通过唯一索引来匹配关联条件。
- const:这种根据索引直接可以快速找到数据的过程,const意思是恒定。所以你以后在执行计划中看到const的时候,就知道他就是直接通过索引定位到数据,速度极快,这就是const的意思。
5. MDC日志
log4j 和 logback提供了MDC(Mapped Diagnostic Context,映射调试上下文)功能,可以在多线程条件下记录日志。MDC可以被看作是一个与当前线程绑定的哈希表,可以向其中添加键值对。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。
6. Java 解析字符串的表达式
学解释器模式了解到的,已经有一些现成的工具了,大部分需求都可以用已有的轮子实现,而不需要自己去手撸解释器。
- Expression4j:一个轻量级的表达式解析器,支持各种数学和逻辑运算符。它简单易用,适合初学者使用。
- JEP(Java Expression Parser):一个功能强大的表达式解析器,支持数学、逻辑、字符串和日期等各种类型的表达式。它提供了灵活的配置选项和自定义函数的功能。
- Apache Commons JEXL:一个基于JEXL语言的表达式引擎,支持各种操作符和函数。它易于集成和使用。
7. UDF是什么
UDF 是 User-Defined Function(用户自定义函数)的缩写。这个术语在不同的上下文中有不同的含义,但总体来说,UDF 意味着用户可以自行定义的函数。
以下是几个不同领域中 UDF 的应用:
- 数据库:在数据库领域,UDF 是用户自定义的函数,可以在 SQL 查询中使用。这样的函数允许用户根据特定需求定义自己的函数,以便在 SQL 查询中调用。这样的函数通常以编程语言(如 PL/SQL、T-SQL 等)编写,然后在数据库中注册以供使用。
- 数据处理和分析:在数据处理和分析领域,UDF 可能是指用户自定义的函数,用于在数据处理框架(如 Apache Spark、Apache Hive 等)中执行特定的数据转换或计算。用户可以编写自己的函数并将其应用于大规模的数据集。
- Excel:在 Microsoft Excel 中,用户可以编写自定义函数以扩展 Excel 的功能。这些自定义函数也被称为 UDF。
- 编程语言:在编程语言中,特别是在脚本语言中,UDF 可能指用户自定义的函数,可以在脚本中调用。这允许开发人员根据需要创建自己的函数,以增强编程语言的功能。
总的来说,UDF 意味着用户可以根据自己的需求定义和使用的函数。这使得在不同的应用领域中能够更灵活地适应特定的需求。
8. linux inode(明明服务器上还有内存,但是存不了文件)
当Linux系统中的inode(索引节点)用完时,系统将无法创建新的文件或目录,甚至无法复制或移动已有文件或目录,原因如下:
- Inode是文件和目录的元数据:Inode 包含有关文件或目录的元数据信息,如文件大小、创建时间、所有者等。每个文件或目录都对应一个唯一的inode。当文件系统中的inode用完时,就表示系统不能再创建新的文件或目录,因为无法为它们分配唯一的inode。
- 磁盘空间并不是唯一限制:虽然磁盘上可能还有足够的空间,但如果没有足够的inode可用,系统仍然无法创建新的文件或目录。
- 文件系统超过inode限制:文件系统在创建时就分配了一定数量的inode。如果文件系统中的文件数量增长得很快,而没有相应地增加inode的数量,就有可能导致inode用完。这通常发生在文件系统设计不当或者未经充分规划的情况下。
- 删除文件并不总是释放inode:当文件被删除时,相应的inode会被标记为未使用,但并不总是立即释放。如果文件被频繁创建和删除,未及时释放的inode会导致inode用尽的问题。
解决这个问题的方法通常包括:清理不必要的文件、调整文件系统参数、更换文件系统。在调整文件系统参数或更换文件系统时,务必备份重要数据,并确保操作的可逆性。
9. redis和memcache最佳实践总结
redis:支持数据持久化,有快照和追加文件两种方式。
- 在多核心CPU上,应该部署多个Redis实例。最极致就是把核心绑定上,让redis只在某个核心上运行,不切核。
- 利用单线程处理的天生优势,可以昨分布式锁。
- 因为可以持久化,可以当做数据库用。
memcache:不支持数据持久化
- 支持多线程,致的性能适合高并发场景。单个实例可以达到10万 QPS。
- 因为内存预分配机制,所以千万不要大幅度改变缓存数据的大小。
- 没有集群配置,如果做分布式缓存,可以在Client端扩展数据分片读取,写入。
10. mysql主从模式
从库并不是能够无限多的,从库越多,同步链路越长,数据一致性越差。从库多,会导致对带宽的需求也增多,因为同步是走网络的,如果带宽不够同步会受到影响。
主从怎么保证数据一致性?
11. mysql数据分片
垂直分片:按照功能划分
水平分片:按照哈希算法分数据,但是需要注意的是哈希算法不一定均匀。
在使用的时候,可以搞多套连接池,比如读写连接池,不同业务用不同的连接池。或者可以搞一个中间件实现读写分离,大厂都这么搞。
再比如,美团外卖还可以按照城市分,具体怎么分没有标准答案,要看实际场景
12. 异步调用编排-CompletableFuture
CompletableFuture 是 Java 8 引入的一个类,用于支持异步编程和构建异步操作的工具。它提供了一种方便的方式来处理异步计算,使得编写异步代码更加直观和简单。
13. 全链路日志
全链路日志(End-to-End Logs)通常指的是在一个系统或应用的整个处理链路中,从请求发起到最终响应返回,记录的完整日志信息。这包括了整个请求和响应的生命周期内的所有关键步骤和事件。全链路日志对于排查问题、性能优化以及系统监控都非常有价值。
以下是全链路日志的一些关键特点和作用:
- 覆盖整个处理链路:全链路日志记录了整个请求和响应的处理链路,包括前端、后端、中间件、数据库等各个组件和服务的交互过程。
- 时间戳和耗时信息:全链路日志通常包括每个步骤的时间戳和耗时信息,这有助于分析和优化系统的性能。
- 关键事件记录:记录关键事件和操作,例如请求的开始和结束、中间步骤的执行、异常的发生等。这有助于定位问题和分析系统行为。
- 请求标识和关联:每个请求都会有一个唯一标识符,可以在全链路的不同阶段传递和关联。这对于在分布式系统中跟踪请求的流程非常有帮助。
- 错误和异常信息:记录请求过程中出现的错误和异常信息,有助于及时发现问题并进行故障排除。
- 日志聚合和分析:全链路日志可以通过日志聚合工具进行收集和分析,以便进行系统性能监控、故障排查和业务分析。
- 安全和合规性:全链路日志可以用于确保系统的安全性和合规性,通过记录用户行为和系统操作来进行审计和监测。
14. 负载均衡
硬件负载均衡、软件负载均衡、DNS负载均衡
负载均衡算法用于指定向哪个服务器分配请求的策略,大概有这几种:轮询、最小连接数、最小响应时间、iphash、加权轮询、随机。
一般不用iphash,因为hash本身就不均衡。
15. 百度云阿里云
百度云:文件重复量很高,只要用的人足够多,重复的会越来越高,卖存储就等于卖数字。
阿里云:卖服务器,一个服务器卖给多个人
16. kafka
后来者,性能最好。可以设置保存时间,可以发布订阅,让一个消息被多次消费(每个消费者都要有offset记录消费到哪里了)
消息队列的好处:解耦不同业务;异步处理;流量削峰;
kafka为什么快?:硬盘可以连续写连续读,硬盘指针不需要来回转。
kafka分了片还能保证顺序吗?(面试题)只用一片,就是队列了,有序队列很难分布式。
想保证顺序一致就别分片,想要性能做了分片,可就别想顺序一致性了。
17. 简历注意事项
要量化,你做了什么事情,这个事情带来多少好处
要把技术写上去,要有亮点
不要总说业务,要讲技术。使用什么技术作什么事情
标红重要内容,不要写太多技术,比如git、maven也要写,太捞
java8可别新特性了,那都快进博物馆了!!!
也不能太少,太少像个demo
也不能太多,太多重点不突出,面试官看的想吐
要有积累,平时就积累。比如shit山代码优化,代码性能优化
要会的:并发编程、JVM、MYSQL、缓存、消息队列、开源分布式中间件,了解linux下devops
18. caffeine
在Java中,Caffeine是一个用于缓存的开源库。它提供了一个高性能、轻量级的缓存实现,旨在提供快速、可靠的缓存服务。Caffeine的设计目标是在不牺牲性能的情况下,提供简单而强大的缓存功能。
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineDemo {
public static void main(String[] args) {
// 创建一个最大容量为100,过期时间为5分钟的缓存
Cache<String, String> cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
// 在缓存中存储值
cache.put("key1", "value1");
cache.put("key2", "value2");
// 从缓存中获取值
String value1 = cache.getIfPresent("key1");
String value2 = cache.getIfPresent("key2");
String value3 = cache.getIfPresent("key3"); // 不存在的键将返回null
System.out.println("Value for key1: " + value1);
System.out.println("Value for key2: " + value2);
System.out.println("Value for key3: " + value3); // 不存在的键返回null
}
}
19. jdk9 finalize被废弃
finalize 方法在 Java 中被认为是不稳定的主要原因有以下几点:
- 不确定性的执行时机:Java 的垃圾回收器在执行 finalize 方法的时机上是不确定的。这意味着开发者无法精确控制何时进行资源清理。由于垃圾回收的执行时间依赖于多个因素,包括内存压力、垃圾回收算法等,这使得 finalize 方法难以保证在需要的时候被及时执行。
- 性能开销:调用 finalize 方法可能导致性能开销,因为它需要在垃圾回收器中执行,并可能需要等待垃圾回收周期。这会引入不确定性和延迟,对应用程序的性能产生负面影响。
- 难以预测的对象生命周期:在某些情况下,对象可能在不再被引用的情况下仍然存活,因为垃圾回收器可能在某个时刻决定要回收该对象,而在此之前对象的 finalize 方法可能不会被调用。这使得对象生命周期的管理变得不可预测。
- 垃圾回收器改进的需求:Java 虚拟机的垃圾回收机制一直在不断改进,而 finalize 方法的不确定性和性能问题导致了一些实际的挑战。为了提高垃圾回收性能和可预测性,引入了更先进的机制,如 Cleaner 接口。
综合这些问题,Java 社区倾向于不推荐使用 finalize 方法来执行重要的资源清理操作。相反,更现代、可控的资源管理方式,如 try-with-resources 语句、AutoCloseable 接口和 Cleaner 接口,更好地满足了资源管理的需求,避免了 finalize 方法的不稳定性和性能开销。
20. jdk21虚拟线程
在Go语言中,"协程"(goroutine)是一种轻量级线程的实现。携程是Go语言中并发编程的核心概念之一,它提供了一种更加轻便、高效的并发处理方式。
协程是由Go语言的运行时系统(runtime)管理的,而不是由操作系统管理的线程。每个协程都是一个独立的执行单元,它由Go运行时系统调度,而不是由操作系统内核调度。这使得协程的创建和切换非常轻量级,开发者可以轻松创建数千甚至数百万个协程,而不会导致系统资源的过度消耗。
go的协程很出名,java是个大杂烩,自然也要跟进。
虚拟线程是由JEP 425提出的预览功能,并在JDK 19中发布,JDK 21中最终确定虚拟线程。
虚拟线程成本低且丰富,因此永远都不应被池化:每个应用程序任务应该创建一个新的虚拟线程。因此,大多数虚拟线程将是短暂的,且具有浅层次的调用栈,执行的操作可能只有一个HTTP客户端调用或一个JDBC查询。相比之下,平台线程是重量级且代价昂贵,因此通常必须池化。它们倾向于具有较长的生命周期,具有深层次调用栈,并在许多任务间共享。
总之,虚拟线程保留了与Java平台设计和谐一致的可靠的 thread-per-request 编程风格,同时最大限度地利用硬件资源。使用虚拟线程无需学习新概念,尽管可能需要放弃为应对当前线程成本高昂而养成的习惯。
tomcat11在jdk21没出生的时候就支持虚拟线程了。
多个虚拟线程对应一个真正的线程。没有频繁切换问题。能够更有效地利用资源。
21. doris执行update语句失败
update 命令只能在 Unique 数据模型的表中执行。
22. 记一次愚蠢的bug
项目催办发消息功能是我做的,22号测试测出来bug,说是数据催办失败了,有时候好使,有时候不好使。紧接着23号模型也说催办不好使。
但是我在测试环境测试好多遍,都没有问题,代码和表结构也一样,那为什么发不出去消息了呢?
首先,我想到了看打印的消息接收人日志,但是很尴尬,日志没有打印出来,日志是在判空之后打印的,是空的直接不打印,很蠢,这是我认为第一个蠢点。那没办法,改代码吧,加日志,这次把所有关键信息按步骤都打印出来了。拿着数据去表里一查,没问题啊,数据都查出来了,那为啥发不过去呀。
这时候我去看了代码,看到自己用了addAll方法,且没做参数判空,然后以为是这个问题,但是经过测试,如果是null,全局异常会捕获到。结合测试的时候看的日志,并没有报错,只是单纯没有消息接收人id数据。
这就奇了怪了,明明可以查出来数据,但是代码查不到。这咋回事?
这是最蠢的点,我TM在sql里写了库名,例如:A库.B表,这么搞如果数据库没变名,那自然是没问题的,但是一旦换了库,库不叫A了,那这个sql是查不出来数据的,WC我怎么干出来这么蠢的事。本来数据库名在配置文件里切换就ok了,我这么一写,库都切不了了。
复盘了一下,一是,一开始写sql,是达梦查询需要加库名,所以sql在达梦写完直接复制过去了,也能用,就没注意到这个问题。二是idea全局搜索,有些东西并不能查到,这次我的库名,全局搜索就搜不到,不能完全相信它,还是要自己看。
总之,这类蠢问题,一开始就应该杜绝,希望这么蠢的问题以后不要再写出来。
23. Warning equals/hashCode on Lombok's @Data annotation with inheritance
lombok如果一个类继承了别的类,加上@Data注解之后会报警:Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '(callSuper=false)' to your type...
@Data
@EqualsAndHashCode(callSuper = true) // 加上这个就没了
public class AAA extends BBB implements Serializable {}
加上@EqualsAndHashCode(callSuper = true) 意思是计算hash和进行equals比较时,包括父类的属性。
不加的话,去看AAA的class文件,你会发现有一行是:int result = 1;加了之后,这一行会变为:int result = super.hashCode();也就是加了会使用父类属性。
还有一种方案是定义一个lombok配置文件,在配置文件里面设置。不管怎样,这个问题必须要解决,万一出问题,这个可不好发现,头发要掉好多。
24. Later equals never
代码整洁之道,提出的观点,确实正确,想想也是好多代码想着等以后优化,可是再也没有以后。