瓜子二手车二面通过了,但没去。。。

瓜子二手车二面通过了,但没去。。。

RLock lock = redisson.getLock("myLock");

lock.lock;

try{

// 业务逻辑

} finally{

lock.unlock;

}

2. mysql的事务四大特性是什么?

事务的 acid 四大特性:

原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。

一致性(Consistency):是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。

隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。

持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

MySQL InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?

持久性是通过 redo log (重做日志)来保证的;

原子性是通过 undo log(回滚日志) 来保证的;

隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;

一致性则是通过持久性+原子性+隔离性来保证;

3. 慢SQL问题怎么排查和解决?

分析查询语句:使用EXPLAIN命令分析SQL执行计划,找出慢查询的原因,比如是否使用了全表扫描,是否存在索引未被利用的情况等,并根据相应情况对索引进行适当修改。

创建或优化索引:根据查询条件创建合适的索引,特别是经常用于WHERE子句的字段、Orderby 排序的字段、Join 连表查询的字典、 group by的字段,并且如果查询中经常涉及多个字段,考虑创建联合索引,使用联合索引要符合最左匹配原则,不然会索引失效

避免索引失效:比如不要用左模糊匹配、函数计算、表达式计算等等。

查询优化:避免使用SELECT *,只查询真正需要的列;使用覆盖索引,即索引包含所有查询的字段;联表查询最好要以小表驱动大表,并且被驱动表的字段要有索引,当然最好通过冗余字段的设计,避免联表查询。

分页优化:针对 limit n,y 深分页的查询优化,可以把Limit查询转换成某个位置的查询:select * from tb_sku where id>20000 limit 10,该方案适用于主键自增的表。

读写分离:搭建主从架构, 利用数据库的读写分离,Web服务器在写数据的时候,访问主数据库(master),主数据库通过主从复制将数据更新同步到从数据库(slave),这样当Web服务器读数据的时候,就可以通过从数据库获得数据。这一方案使得在大量读操作的Web应用可以轻松地读取数据,而主数据库也只会承受少量的写入操作,还可以实现数据热备份,可谓是一举两得。

优化数据库表:如果单表的数据超过了千万级别,考虑是否需要将大表拆分为小表,减轻单个表的查询压力。也可以将字段多的表分解成多个表,有些字段使用频率高,有些低,数据量大时,会由于使用频率低的存在而变慢,可以考虑分开。

使用缓存技术:引入缓存层,如Redis,存储热点数据和频繁查询的结果,但是要考虑缓存一致性的问题,对于读请求会选择旁路缓存策略,对于写请求会选择先更新 db,再删除缓存的策略。

4. 线程池用过没有? 说说他的核心参数?

线程在正常执行或者异常中断时会被销毁,如果频繁的创建很多线程,不仅会消耗系统资源,还会降低系统的稳定性,一不小心把系统搞崩了。

使用线程池可以带来以下几个好处:

线程池内部的线程数是可控的,可以灵活的设置参数;

线程池内会保留部分线程,当提交新的任务可以直接运行;

方便内部线程资源的管理,调优和监控;

所以,线程池是为了减少频繁的创建线程和销毁线程带来的性能损耗,线程池的工作原理如下图:

当用户提交了一个任务,接下来这个任务将如何执行都是由这个阶段决定的。首先,所有任务的调度都是由execute方法完成的,这部分完成的工作是:检查现在线程池的运行状态、运行线程数、运行策略,决定接下来执行的流程,是直接申请线程执行,或是缓冲到队列中执行,亦或是直接拒绝该任务。其执行过程如下:

首先检测线程池运行状态,如果不是RUNNING,则直接拒绝,线程池要保证在RUNNING的状态下执行任务。

如果workerCount < corePoolSize,则创建并启动一个线程来执行新提交的任务。

如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中。

如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务。

如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。

线程池七大核心参数如下所示:

corePoolSize:线程池核心线程数量,如果设置为5,线程池初始化后默认保持5个线程待命。默认情况下,线程池中线程的数量如果 <= corePoolSize,那么即使这些线程处于空闲状态,那也不会被销毁。

maximumPoolSize:线程池允许的最大线程数。当任务队列已满,且当前线程数小于 maximumPoolSize时,线程池会创建新的线程来处理任务,直至线程数达到 maximumPoolSize。

keepAliveTime:当线程池中线程的数量大于corePoolSize,并且某个线程的空闲时间超过了keepAliveTime,那么这个线程就会被销毁。

unit:就是keepAliveTime时间的单位。

workQueue:工作队列。当没有空闲的线程执行新任务时,该任务就会被放入工作队列中,等待执行。

threadFactory:用于创建线程的工厂。通过自定义线程工厂,你可以为线程设置名称、优先级等属性。

handler:拒绝策略。当一个新任务交给线程池,如果此时线程池中有空闲的线程,就会直接执行,如果没有空闲的线程,就会将该任务加入到阻塞队列中,如果阻塞队列满了,就会创建一个新线程,从阻塞队列头部取出一个任务来执行,并将新任务加入到阻塞队列末尾。如果当前线程池中线程的数量等于maximumPoolSize,就不会创建新线程,就会去执行拒绝策略

5. 线程池的拒绝策略有哪些?

当线程池的任务队列满了之后,线程池会执行指定的拒绝策略来应对,常用的四种拒绝策略包括:CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy,此外,还可以通过实现RejectedExecutionHandler接口来自定义拒绝策略。

四种预置的拒绝策略:

CallerRunsPolicy,使用线程池的调用者所在的线程去执行被拒绝的任务,除非线程池被停止或者线程池的任务队列已有空缺。

AbortPolicy,直接抛出一个任务被线程池拒绝的异常。

DiscardPolicy,不做任何处理,静默拒绝提交的任务。

DiscardOldestPolicy,抛弃最老的任务,然后执行该任务。

自定义拒绝策略,通过实现接口可以自定义任务拒绝策略。

6. SQL题:一张表里面有两列信息, 一列自增ID 一列对应的email,email是有重复项的,让构思一个SQL进行email去重,留下最新的email信息

假设表名为 your_table,自增 ID 列名为 id,email列存储邮件信息。

SELECTt1.*

FROMyour_table t1

INNERJOIN(

SELECTemail, MAX(id) ASmax_id

FROMyour_table

GROUPBYemail

) t2 ONt1.email = t2.email ANDt1.id = t2.max_id;

步骤解析:

子查询 t2按 email分组并找到每组最大的 id。

通过内连接原表 t1,匹配 email和对应的最大 id,从而筛选出每个email的最新记录。

假设原始数据:

id

email

1

a@example.com

2

b@example.com

3

a@example.com

执行查询后结果:

id

email

2

b@example.com

3

a@example.com

7. 项目问题

项目介绍

项目中你觉得有哪些技术亮点

项目是怎么使用的线程池?怎么设置的参数?

瓜子二手车(二面)1. HTTP 和 HTTPS的区别是什么?

区别主要有以下四点:

HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。

HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。

两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。

HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

2. TLS的握手流程说一下?

传统的 TLS 握手基本都是使用 RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书文件其实就是服务端的公钥,会在 TLS 握手阶段传递给客户端,而服务端的私钥则一直留在服务端,一定要确保私钥不能被窃取。

在 RSA 密钥协商算法中,客户端会生成随机密钥,并使用服务端的公钥加密后再传给服务端。根据非对称加密算法,公钥加密的消息仅能通过私钥解密,这样服务端解密后,双方就得到了相同的密钥,再用它加密应用消息。

我用 Wireshark 工具抓了用 RSA 密钥交换的 TLS 握手过程,你可以从下面看到,一共经历了四次握手:

TLS 第一次握手

首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息:

(1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。

(2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。

(3)客户端支持的密码套件列表,如 RSA 加密算法。

TLS 第二次握手

服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:

(1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。

(2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。

(3)确认的密码套件列表,如 RSA 加密算法。(4)服务器的数字证书。

TLS 第三次握手

客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。

如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:

(1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。

(2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。

(3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。

上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。

服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。

TLS 第四次握手

服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。

然后,向客户端发送最后的信息:

(1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。

(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。

3. 如果用户说系统使用的时候会偶尔卡顿,该怎么排除问题?

慢SQL:使用数据库自带的慢查询日志功能,设置合适的时间阈值,找出执行时间过长的 SQL 语句,分析 SQL 执行计划,查看是否存在全表扫描、索引未使用等问题。为查询语句涉及的字段添加合适的索引;对复杂的 SQL 进行拆分,避免一次性处理大量数据;优化查询逻辑,减少子查询和嵌套查询的使用。

慢接口:利用 APM(应用性能监控)工具,如 SkyWalking、Pinpoint 等,监控接口的响应时间,找出响应慢的接口。在代码中添加日志记录接口的处理时间,分析每个步骤的耗时情况。对接口中的业务逻辑进行拆分和异步处理,减少同步操作;缓存一些常用的数据,避免重复查询数据库或进行复杂计算;优化算法和数据结构,提高代码执行效率。

Full GC:使用 JVM 自带的工具,如 VisualVM、jstat、jmap 等,监控 JVM 的内存使用情况和垃圾回收频率。查看 GC 日志,分析 Full GC 的触发原因和耗时。调整 JVM 的堆内存大小,避免内存过小导致频繁的 Full GC;选择合适的垃圾回收器,根据应用的特点和服务器资源进行配置;优化代码中的对象创建和销毁,减少内存泄漏的可能性。

线程阻塞和死锁:使用线程分析工具,如 VisualVM 的线程分析功能,查看线程的状态和堆栈信息,找出阻塞或死锁的线程。在代码中添加日志,记录线程的执行情况,辅助定位问题。减少同步代码块的使用,避免锁的嵌套和长时间持有;使用更细粒度的锁,降低锁的竞争;合理设置线程池的参数,避免线程池耗尽或线程创建销毁过于频繁。

4. 闲聊

为什么想换实习?

本科和硕士阶段学了哪些课程?

反问:java的发展方向和学习路线

相关科技文章

耀光 LOL 装备大全
365bet体育在线导航

耀光 LOL 装备大全

⌚ 11-07 👁️ 7470
率土重聚商店在哪
365bet体育在线导航

率土重聚商店在哪

⌚ 08-30 👁️ 3095
中国联通月租具体是多少钱?如何选择合适的套餐?
外勤365下载安装

中国联通月租具体是多少钱?如何选择合适的套餐?

⌚ 11-18 👁️ 4450
神州全国官方售后服务点热线号码
外勤365下载安装

神州全国官方售后服务点热线号码

⌚ 02-03 👁️ 5058
不知道CFG桩如何施工,如何检测的看这里!
365bet体育在线导航

不知道CFG桩如何施工,如何检测的看这里!

⌚ 11-25 👁️ 590

合作伙伴