12.TCP和Http的区别是什么
TCP是传输层协议,负责建立可靠的点对点连接,确保数据有序、完整地传输(如铁路轨道);
HTTP是应用层协议,基于TCP构建,定义了Web服务交互的报文格式和规则(如货运订单)。
TCP关注数据如何可靠送达,通过三次握手建立连接、流量控制等机制保证传输;HTTP关注传输内容的意义,提供请求/响应语义(GET/POST等)和无状态通信。
补充:
说一下什么是三次握手四次挥手
三次握手:首先客户端向服务端发送SYN=1和初始序列号SEQ给服务器,服务器接收到后向客户端发送ACK=1、SYN=1、和自己的序列号,客户端接收到后向服务端发送ACK=1和被+1之后的SQE给服务端这就实现了三次握手,这三次握手中,第一次握手服务器确定自己有接的能力和对方有发的能力、第二次握手客户端确定了自己有发和接能力对方有发和接的能力、第三次握手客户端和服务端都确定了自己和对方都有发和接的能力
四次挥手:首先客户端向服务端发送FIN和初始序列号想要停止发送断开连接,服务端接收到后向客户端发送ACK=1和初始序列号,这时客户端之前请求的数据服务端还没有发送完,等服务器发送完之后服务端又向客户端发送FIN=1 ACK=1 和序列号给客户端,客户端接收到之后向服务器发送ACK=1和+1后的序列号。
握手确保双方收发能力正常,挥手则保证数据完整传输
13.线程跟进程的区别是什么
线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。
14.进程之间是怎么进行通讯的
管道 消息队列 共享内存 信号量 信号 Socket
补充:线程之间是怎么进行通讯的
1)共享内存配合synchronized
或volatile
保证线程安全;
2)阻塞队列(如LinkedBlockingQueue
)实现生产者-消费者模式;
3)等待/通知机制(wait()/notify()
)进行线程协作;
5)管道流(PipedInputStream
/PipedOutputStream
)定向传输数据。
15.java创建线程的方式有哪些
继承Thread类 实现Runnable接口 实现Callable接口与FutureTask 使用线程池
16.线程池的核心参数(重复出现)
17.java中有那些锁 读写锁知道吗 读写锁如何实现
乐观锁
悲观锁
可重入锁
读写锁:读写锁(ReadWriteLock) 是一种特殊的锁机制,它通过分离读锁(共享)和写锁(独占)来提升并发性能:多个线程可以同时持有读锁(允许并发读),但写锁是排他的(读写、写写互斥)。
ava中通过ReentrantReadWriteLock
实现,其核心是一个int状态值(state):高16位记录读锁数量,低16位记录写锁重入次数,通过CAS操作和队列管理实现线程安全。
条件锁
分布式锁
18.Redis常用的数据类型有哪些
字符串 哈希 列表 集合 有序集合
19.Redis的持久化机制
三种实现方式
RDB:通过创建时间点快照来实现,在指定的时间间隔内将 Redis 某一时刻的数据保存到磁盘上的 RDB 文件中,当 Redis 重启时,可以通过加载这个 RDB 文件来恢复数据。
AOF:通过记录每个写操作命令,并将其追加到 AOF 文件来实现持久化,Redis 服务器宕机后可以通过重新执行这些命令来恢复数据。
这两种方式也可以一起使用:在 AOF 重写期间,先以 RDB 格式将内存中的数据快照保存到 AOF 文件的开头,再将重写期间的命令以 AOF 格式追加到文件末尾。
20.常用的Linux命令有哪些 查看CPU占用 查看端口号是否被占用 查看进程信息
top
netstat
ps
21.MVCC机制
MVCC也叫多版本并发控制
MVCC 通过创建数据的多个版本和使用快照读取来实现并发控制。读操作使用旧版本数据的快照,写操作创建新版本,并确保原始版本仍然可用。这样,不同的事务可以在一定程度上并发执行,而不会相互干扰,从而提高了数据库的并发性能和数据一致性。
它主要是依赖于三块来实现的,一个是隐藏字段、Read View 、undo log
在内部实现中,InnoDB
通过数据行的 事务ID(DB_TRX_ID
)和 Read View
来判断数据的可见性,如不可见,则通过数据行的 回滚指针(DB_ROLL_PTR
)找到 undo log
中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View
之前已经提交的修改和该事务本身做的修改
说一下项目的业务逻辑和遇到的一些比较棘手的问题有哪些
1.索引有哪些类型 索引的数据结构是什么(重复出现)
2.回表的概念是什么(重复出现)
3.数据结构有哪些(重复出现)
数组和链表有什么区别
存储结构:数组是连续内存,支持 O(1)
随机访问;链表是非连续内存,通过指针链接,只能顺序访问。
插入/删除:链表在任意位置插入/删除只需 O(1)
(修改指针),而数组需要 O(n)
(移动元素)。
内存占用:链表每个节点需额外存储指针,而数组只需存储数据。
4.MyISAM 和 InnoDB 有什么区别
1)MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
2)MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。
3)MyISAM 不支持外键,而 InnoDB 支持外键。
4)MyISAM 不支持数据库异常崩溃后的安全恢复,而 InnoDB 支持(复的过程依赖于 redo log
)。
5.类加载过程(重复出现)
6.什么是双亲委派机制
双亲委派是 Java 类加载器的工作机制,核心规则是:子加载器在加载类时,会先委派父加载器处理,只有当父加载器无法完成时,子加载器才会尝试加载。
如何打破双亲委派机制
重写 loadClass()
方法之后,我们就可以改变传统双亲委派模型的执行流程。例如,子类加载器可以在委派给父类加载器之前,先自己尝试加载这个类,或者在父类加载器返回之后,再尝试从其他地方加载这个类。
TOMCAT是打破双亲委派机制的
7.说一下项目中哪里用到了设计模式
8.为什么使用Redis?
访问速度更快 高并发 功能全面 除了可以用作缓存之外,还可以用于分布式锁、限流、消息队列、延时队列等场景,功能强大!
如何保证Redis和mysql缓存数据一致性?
一般采用先操作数据库在删除缓存,但在这个过程中缓存可能会出现删除失败导致读取到脏数据,我们可以采用延迟双删,删除失败我们还需要删除重试,我们可以使用通过异步发送需要删除的key到MQ,让其监听mq,来进行重试,但是这些逻辑都写到一个系统里的话过于耦合了,我们可以采用阿里的一个canal来监听binlog日志,把删除缓存的操作让canal去做,如果出现删除重试也放在canal去做,从而进行解耦,来实现最终一致性。
9.Redis为什么这么快
首先Redis是基于内存的,并且采用高效的数据结构
然后采用单线程模型避免了多线程竞争
还用它使用了IO多路复用处理大量的客户端 Socket 请求
追问 能说一下这个IO多路复用吗
IO多路复用就是一个或多个线程处理多个TCP连接
多路复用一共有三种方式 select poll epoll
第一个select这种采用的是轮询加遍历的方式在客户端操作服务器时会创建三种文件描述符简称FD分别是写、读和异常,select会阻塞监视这三种FD,等到数据有可读、可写、出异常和超时的时候都会返回,返回后通过遍历fdset来找到就绪的fd然后去触发相应的IO操作
第二个poll模型的原理和select差不多一致也是采用的轮询+遍历,唯一的区别就是poll模型采用的是链表来存储fd(没有fd数量的最大限制)
第三个epoll采用时间通知机制来触发相关的IO操作,没有fd个数的限制,从用户态拷贝到内核态只需要一次,因为塔主要是通过调用系统底层的函数来实现注册激活fd,主要有这三个函数第一个epoll_create函数在系统启动的时候会在Linux内核去申请一个B+树结果的文件系统然后再返回epoll对象,第二个就是epoll_ctl()函数在没新建一个连接的时候会同步更新epoll里的fd并且去绑定一个callback回调函数,第三个是epoll_wait函数会轮询所有callback集合并且去触发对应的IO操作
1.jvm了解吗,堆跟栈有什么区别,堆和栈谁大谁小
了解过
堆更大
堆存放所有对象,栈仅存方法调用的临时数据。
2.有没有做过一些jvm调优
3.spring核心思想有了解吗,说一下
Spring是一个轻量级的IoC和AOP容器框架,是为Java应用程序提供基础性服务的一套框架 主要是依赖于IOC AOP DI来实现
通过控制反转实现了对象的创建和对象间的依赖关系管理。
通过AOP,可以将这些事务管理、安全控制等这些点模块化,提高代码的可维护性和可重用性。
通过DI解决了硬编码问题
IOC
IOC:(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用。
控制:指的是对象创建(实例化、管理)的权力
反转:控制权交给外部环境(Spring 框架、IoC 容器)
4.为什么重写equals()就一定要重写hashCode()
因为如果两个对象相等则两个对象的hashcode一定是相等的,
如果通过equlas判断两个对象相等了,而hashCode却不相等可能会导致重复存储逻辑相等的对象,还有查询时hashMap会通过hashcode去定位哈希桶,再去用equals匹配键,hashcode不一致即使equals返回true,也可能会直接返回null值
5.springboot相比较spring框架有什么特别的地方
Spring Boot 提供了自动化配置,大大简化了项目的配置过程。通过约定优于配置的原则,很多常用的配置可以自动完成,开发者可以专注于业务逻辑的实现。
Spring Boot 提供了快速的项目启动器,通过引入不同的 Starter,可以快速集成常用的框架和库(如数据库、消息队列、Web 开发等),极大地提高了开发效率。
Spring Boot 默认集成了多种内嵌服务器(如 Tomcat、Jetty、Undertow),无需额外配置,即可将应用打包成可执行的 JAR 文件,方便部署和运行。
springboot和springmvc有什么不同?
“它们解决的问题不同。Spring MVC 是 Spring 的 Web 框架,核心提供 Controller 开发、请求路由和数据绑定能力,需要手动配置 DispatcherServlet 等组件。 而 Spring Boot 是更高层的解决方案,通过起步依赖(如 starter-web)自动集成 Spring MVC,并添加了内嵌服务器、监控等生产级特性。
6.springboot的自动配置原理(重要理解)
- 我们的启动类上有@SpringBootApplication
子注解@SpringBootConfiguration,间接被@Configuration修饰,即启动类是一个源配置类
子注解@ComponentScan,对源配置类所在的Package进行组件扫描
子注解@EnableAutoConfiguration
,最终导入一个AutoConfigurationImportSelector
组件来实现自动配置
这个组件中会通过SpringFactories机制
去读取META-INF/spring.factories
文件中的所有自动配置类。这是一种SPI机制
然后根据这些自动配置类上的条件注解@Conditional
进行过滤,过滤出满足条件的自动配置类
然后通过Spring提供的ImportSelector接口
来加载这些自动配置类
从而得到这些自动配置类的BeanDefinition
最后根据BeanDefinition实例化对象
7.缓存穿透、缓存击穿、缓存雪崩是什么怎么解决(重要理解)
缓存穿透就是大量的不合法读请求去读数据,正常先去缓存上读,但缓存上没有,那么这些大量的请求就会落实到数据库中,面对这么多请求,数据库压力就会非常大就很有可能导致数据库宕机。
解决方案:最基本的首先要做好参数校验,一些不合法的参数请求直接抛异常信息给客户端
1)缓存无效 key:如果缓存和数据库都查不到某个 key 的数据,就写一个到 Redis 中去并设置过期时间
2)布隆过滤器
3)接口限流:根据用户或者 IP 对接口进行限流,对于异常频繁的访问行为,还可以采取黑名单机制
缓存击穿就是某个热点key突然失效,同时大量请求涌入,导致数据库压力激增
解决方案:
1)永不过期(不推荐):设置热点数据永不过期或者过期时间比较长。
2)提前预热(推荐):针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
3)加锁(看情况):在缓存失效后,通过设置互斥锁确保只有一个请求去查询数据库并更新缓存
缓存雪崩就是大量缓存key同时失效或缓存服务宕机,导致所有请求直接打到数据库
解决方案:
针对 Redis 服务不可用的情况:
Redis 集群:采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
多级缓存:设置多级缓存,例如本地缓存+Redis 缓存的二级缓存组合
针对大量缓存同时失效的情况:
设置随机失效时间:这样可以避免大量缓存同时到期,从而减少缓存雪崩的风险
提前预热(推荐):针对热点数据提前预热,将其存入缓存中并设置合理的过期时间