你好,我是二哥呀。
上周有读者跑过来说,二哥,思前想后,还是决定签约阿里云放弃京东的 offer 了,一是觉得京东今年给的年包太大怕后面出意外,二是我一直对阿里系比较青睐,这次有机会亲身体验,也算是圆满了。
我觉得他的想法完全没问题。
星球里之前也有一些球友拿到阿里云的 offer,其中有一个是拿到了蚂蚁的海外钱包支付业务,和阿里云的政企事业部专业云,你会劝他选择哪一个呢?
我从牛客上也统计了一波阿里云的薪资待遇给大家做个参考,不得不说,今年阿里云还是挺舍得给钱的。
给了总包 45,云网络,作息时间为早上 9 点半到晚上 9 点半,午休一个半小时,需要值班和 oncall,压力较大 硕士 985,Java 岗,给了 28k*16,杭州地区,算是 SP 了 浙江大学,AI 工程师,也给了 28k,去数据库做 AI 落地的,算是批发价 2 本 9 硕,技术服务,给了 29k,还有 2k 的房补,偏售后,主要解决客户日常问题和服务器部署等 硕士海归,开发岗,给了 27k,没有签字费,政府人才补贴能给 6 万,还有交通补助 硕士 985,后端岗,给了 30k,实习转正
阿里云成立于 2009 年,一开始主要做淘天、支付宝的底层支撑,2013 年之后开始加速商业化布局。
目前,有 80% 的科技企业、超过 1000 家大型政企、800+央国企运行在阿里云上。我自己的网站《javabetter.cn》、《paicoding.com》 一开始都部署在阿里云上,今年才刚迁移到腾讯云上。
不过 CDN 和 OSS 仍然用的阿里云,因为我所有博客的图片都在上面,迁移成本比较大。
如果非要给阿里云排个名次的话,我觉得阿里云算是整个阿里系的二哥吧,大哥是已经自立门户的蚂蚁,三弟是淘天。
那接下来,我们就以 Java 面试指南中收录的阿里云面经同学 22 为例,来看看如果想去阿里云的话,应该如何去准备?
1、《30 天速通 Java.pdf》下载 2、三分恶面渣逆袭在线版:https://javabetter.cn/sidebar/sanfene/nixi.html
阿里云面经同学 22 面经
事务隔离级别
事务的隔离级别定了一个事务可能受其他事务影响的程度,MySQL 支持四种隔离级别,分别是:读未提交、读已提交、可重复读和串行化。
幻读和脏读的区别
幻读指的是在同一事务中执行相同的查询时,返回的结果集中出现了之前没有的数据行。这是因为在事务执行过程中,另外一个事务插入了新的数据。
比如说事务 A 在第一次查询某个条件范围的数据行后,事务 B 插入了一条新数据且符合条件范围,事务 A 再次查询时,发现多了一条数据。
-- 事务 A
START TRANSACTION;
SELECT * FROM employees WHERE department = 'HR'; -- 读取到 10 条记录
-- 事务 B
START TRANSACTION;
INSERT INTO employees (id, name, department) VALUES (11, 'John Doe', 'HR');
COMMIT;
-- 事务 A 再次查询
SELECT * FROM employees WHERE department = 'HR'; -- 读取到 11 条记录 (幻读)
COMMIT;
脏读指的是一个事务能够读取另一个事务尚未提交的数据。如果读到的数据在之后被回滚了,那么第一个事务读取到的就是无效的数据。
-- 事务 A
START TRANSACTION;
UPDATE employees SET salary = 5000 WHERE id = 1;
-- 事务 B
START TRANSACTION;
SELECT salary FROM employees WHERE id = 1; -- 读取到 salary = 5000 (脏读)
ROLLBACK;
如何防止幻读?
①、直接使用最高的隔离级别串行化,但会导致大量的锁竞争。
②、使用间隙锁,防止其他事务在间隙范围内插入数据。
③、在可重复读的隔离级别下,MVCC 机制会为每个事务维护一个快照,事务在读取数据时,只能读取到快照中的数据,而不会读取到其他事务插入的数据。
事务的mvcc机制
MVCC 指的是多版本并发控制,简单来说,就是给我们的 MySQL 数据拍个“快照”,定格某个时刻数据库的状态。
在 MySQL 中,MVCC 是通过 undo log 版本链和 ReadView 机制来实现的。
每条记录包含两个隐藏列:最近修改的事务 ID 和指向 Undo Log 的指针,用于构成版本链。 每次更新数据时,会生成一个新的数据版本,并将旧版本的数据保存到 Undo Log 中。 每次读取数据时,会生成一个 ReadView,用于判断哪个版本的数据对当前事务可见。
执行什么命令会加上间隙锁?
当范围查询与锁定操作(如 FOR UPDATE)结合时,InnoDB 会对查询范围内的记录间隙加上间隙锁。
SELECT * FROM table WHERE column > 10 and column < 20 FOR UPDATE;
双亲委派机制
双亲委派模型要求类加载器在加载类时,先委托父加载器尝试加载,只有父加载器无法加载时,子加载器才会加载。
cms和g1的区别
CMS 在 JDK 1.5 时引入,JDK 9 时被标记弃用,JDK 14 时被移除。
CMS 是一种低延迟的垃圾收集器,采用标记-清除算法,分为初始标记、并发标记、重新标记和并发清除四个阶段,优点是停顿时间短,适合延迟敏感的应用,但容易产生内存碎片,可能触发 Full GC。
G1 在 JDK 1.7 时引入,在 JDK 9 时取代 CMS 成为默认的垃圾收集器。
G1 是一种面向大内存、高吞吐场景的垃圾收集器,它将堆划分为多个小的 Region,通过标记-整理算法,避免了内存碎片问题。优点是停顿时间可控,适合大堆场景,但调优较复杂。
spring三级缓存解决循环依赖问题
Spring 通过三级缓存机制来解决循环依赖:
一级缓存:存放完全初始化好的单例 Bean。 二级缓存:存放正在创建但未完全初始化的 Bean 实例。 三级缓存:存放 Bean 工厂对象,用于提前暴露 Bean。
如何使用spring实现事务
在 Spring 中,事务管理可以分为两大类:声明式事务管理和编程式事务管理。
编程式事务可以使用 TransactionTemplate 和 PlatformTransactionManager 来实现,需要显式执行事务。允许我们在代码中直接控制事务的边界,通过编程方式明确指定事务的开始、提交和回滚。
声明式事务是建立在 AOP 之上的。其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在目标方法执行完之后根据执行情况提交或者回滚事务。
Spring 推荐通过 @Transactional 注解的方式来实现声明式事务管理。
介绍事务传播模型
事务的传播机制定义了方法在被另一个事务方法调用时的事务行为,这些行为定义了事务的边界和事务上下文如何在方法调用链中传播。
Spring 的默认传播行为是 PROPAGATION_REQUIRED,即如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
linux常用命令
我自己常用的 Linux 命令有:
top 用来查看系统资源 ps -ef | grep java
查看 Java 进程netstat
查看网络连接ping 测试网络连通性 find 查找文件 chmod 修改文件权限 kill 终止进程 df 查看磁盘空间 mkdir 创建目录、rm 删除文件、cp 复制文件、mv 移动文件 zip 压缩文件、unzip 解压文件等等这些。
springboot常用注解
@SpringBootApplication:Spring Boot 应用的入口,用在启动类上。 还有一些 Spring 框架本身的注解,比如 @Component、**@RestController、@Service、@ConfigurationProperties、@Transactional** 等。
redis高级数据结构的使用场景
就比如说 Zset 吧,它是有序集合,比 set 多了一个排序属性 score。
可以用来实现排行榜,比如技术派实战项目中,我就使用了 Zset 来实现用户活跃排行榜。
介绍NIO BIO AIO
Java 常见的 IO 模型有三种:BIO、NIO 和 AIO。
BIO:采用阻塞式 I/O 模型,线程在执行 I/O 操作时被阻塞,无法处理其他任务,适用于连接数较少的场景。
NIO:采用非阻塞 I/O 模型,线程在等待 I/O 时可执行其他任务,通过 Selector 监控多个 Channel 上的事件,适用于连接数多但连接时间短的场景。
AIO:使用异步 I/O 模型,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程,适用于连接数多且连接时间长的场景。
kill -9 9的意义是什么
kill -9 PID
是一种强制终止进程的方式,其中的 9 表示信号编号,代表 SIGKILL 信号。
如何做到强制终止线程
设置线程的中断标志,通知线程优雅地终止。
class MyTask implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("Running...");
Thread.sleep(1000); // 模拟工作
} catch (InterruptedException e) {
// 捕获中断异常后,重置中断状态
Thread.currentThread().interrupt();
System.out.println("Thread interrupted, exiting...");
break;
}
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new MyTask());
thread.start();
Thread.sleep(3000); // 主线程等待3秒
thread.interrupt(); // 请求终止线程
}
}
中断结果:
ending
一个人可以走得很快,但一群人才能走得更远。二哥的编程星球已经有 6700 多名球友加入了,如果你也需要一个优质的学习环境,戳链接 🔗 加入我们吧。你可以阅读星球专栏、向二哥提问、帮你制定学习计划、精修简历、和球友一起打卡成长。
两个置顶帖「球友必看」和「知识图谱」里已经沉淀了非常多优质的学习资源,相信能帮助你走的更快、更稳、更远。
如果觉得有帮助,不妨随手点个赞、在看、转发三连吧,如果你想第一时间收到推送,也可以给我加个星标🌟谢谢你看我的文章,我们明天见。
最后,把二哥的座右铭送给大家:没有什么使我停留——除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟。共勉 💪。