一、技术问题
1. 数组相关的问题
问题1:map相关问题
- 介绍下map:例如扩容原理,阈值,默认大小,数据结构
- map.put的原理 (这里说下并发下数据丢失问题,并把 concurrenthashmap这个对象引出来,说这个在指定的链表中加了锁,效率好很多等等)
- map.put怎么解决hash冲突(这个我也不知道)
2. 数据加密
问题1:有哪些加密算法
问题2:怎么保证数据安全性
- RSA的加密过程如下: (1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。
(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。 (3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。
3. 为什么用b+
大概说下b+树结构和回表操作 https://blog.csdn.net/weixin_38003389/article/details/86604309
4. 索引的注意事项
从表设计开始讲,1.合理的设计表,2.然后就讲索引,3.讲什么查询才能用到索引等等 https://www.cnblogs.com/heyonggang/p/6610526.html
5. 事务的传播机制
具体的传播机制很难记,这个看自己吧,这个我没回答上来 https://blog.csdn.net/weixin_36162966/article/details/106575192
6. 分布式事务原理(seata)
-
简述:xa我们的业务场景有两个操作,一个减库存,一个生成订单,我们要保证这两个操作的幂等性,他们在不同的服务中,这时候我们可以加 seata 的注解。 他的执行原理是,会先生成一个全局的事务id叫xid,这个xid是一个标识,例如我们的减库存操作他这个服务会开启自己的本地事务,成功失败或者超时等等都会通知tc中心,Tc会记录各个服务是否成功,还有回滚语句,如果有任何一个服务失败,那么他就会去通知之前成功的服务,进行回滚操作。回滚时靠着自己保存的回滚语句进行回滚。如果全部成功,则删除记录的一些回滚信息,并返回成功 -
好处:相较于tcc,减少了两段式提交,对于整个流程都精简了许多,并且是无侵入的。 -
注意事项:在布式事务修改数据的时候,有全局锁和本地锁来处理分布式事务写隔离
https://blog.csdn.net/tianyaleixiaowu/article/details/95208906 https://www.cnblogs.com/zpKang/p/14197704.html
7.redis相关问题
1. 锁如何保证过期时间设置的原子性
解决:使用 setIfAbsent (spring中的方法)来执行原子操作,这个可以加过期时间,是原子性操作;还有就是使用lua脚本去加锁
https://blog.csdn.net/qq_37730370/article/details/107176729
2. redis锁是怎么实现的
就说下这个锁的一个获取流程
3. redis锁如何保证锁过期但是操作没执行完的情况
可以说依照义务来定,设置长一点的时间啊,或者使用redisson的工具类,它提供了看门狗相应的实现,可以动态延长这个过期时间,不过很耗性能,自己依照场景而定吧
4. redis锁你使用在哪些场景
两个点,缓存和锁 缓存:门店信息之类的,可能会存在下面说的不一致问题 锁:具体使用每个增加和修改的地方都加了锁,防止重复点击浪费资源,还有就是锁代码块,库存之类的修改操作,保证不超买超卖问题。
8. spring cloud相关
会问你用了其中的那些组件,都是怎么使用的,这个我不怎么能回答上来alibaba和网飞两套都可以混合着说,就可以直接说我们项目用的那些,说了 spring gateway 他就会问你里面有些什么功能点,怎么实现的
9.并发场景下这么保证数据的安全性和系统的可用性
限流、加锁、加队列等等,还是得百度
10.线程池相关的问题
问题1:(1和10的核心线程和最大线程数)例如100个线程进来,他会进行一些什么步骤
https://www.cnblogs.com/shijianchuzhenzhi/p/12964740.html
问题2:线程池的几个参数说一下(大概说出来就行了)
https://www.cnblogs.com/shijianchuzhenzhi/p/12964740.html
11.spring ioc容器和aop相关的问题
这个自己看吧,可以说spring创建流程和三级缓存还有aop是如何生成的。不会就背
12. mysql 事务隔离级别
ACID等一系列东西,看得深的可以说那些日志(redolog、undolog),mvcc实现原理等等 https://www.cnblogs.com/kismetv/p/10331633.html (ACID等全面的介绍) https://blog.csdn.net/Waves___/article/details/105295060 (mvcc原理)
13. jvm相关问题
问题1:项目中gc用的什么算法?
-
解决1:一般是用分代算法,年轻代使用复制搜集算法,老年代使用标记清除或者标记整理算法。在1.7的时候出现了g1收集器,的整体内存区域是一块一块的内存空间 解决2:具体的落地垃圾回收器是使用了CMS收集器,它主要就是基于标记清除来实现的,可以并发收集,低停顿,缺点就是有内存碎片 复制搜集算法:把年轻代分区,并且把那些没有gc的对象从edent放到 service区,一层层复制 标记清除算法:标记要清除的对象,一次性全部处理,会存在内存碎片 标记整理算法:标记所有要清除的对象,把它们移动到指定的内存区域,然后释放掉遮掉内存区域,会费时间,但没有内存碎片 https://blog.csdn.net/qq_45076180/article/details/107766779
问题2:gc时机
https://www.cnblogs.com/leeego-123/p/11298342.html
问题3:内存模型
15. 锁相关问题
问题1:你知道有哪些锁
- 分布式锁(redis),java自带的单体服务锁(syn关键字、lock工具锁)
问题2:syn和 lock不同点和相同点
不同:
- syn是c++实现的,lock是java实现的,
- lock可手动释放锁,lock可以设置为公平锁,因为其中有许多
- syn关键字内部有一个锁升级的步骤(偏向锁->轻量级锁(自旋锁)->重量级锁(用户态转为内核态))(不懂这些就不要说了)
相同:
- 都是可重入锁
- 都是非公平锁
https://mp.weixin.qq.com/s/2yxexZUr5MWdMZ02GCSwdA (锁升级)
二、项目问题
1. redis缓存不一致问题
-
事情: https://blog.csdn.net/qq_35433716/article/details/86375506 在使用redis做缓存的时候,去修改数据库的数据,并在修改的时候更新redis中的数据,但是在修改完之后,缓存中还是原来的数据。 -
原因 a. 修改的时候,b线程去查询数据,但是发现缓存中没数据了,可能是失效了,就去数据库查询了这个数据,发现缓存中没有,他就到db中查询,然后放到缓存中去的是旧数据 b. 线程a修改了数据,同时线程b修改了数据库,又修改了缓存,这时候线程a修改缓存,就造成了数据一致性问题 -
我们的设计是什么样的: 修改之后,再去更新缓存 -
改成什么样解决了问题: 修改之后,删除缓存信息(虽然还是会存在上面的问题a,但是这种概率非常低,要解决可以使用异步删除,或者选择不使用缓存)
解决:
各种解决都不是很完美的方法,具体看场景
https://blog.csdn.net/u010180738/article/details/105786711(看这篇文章)
额外知识点:
redis 穿透击穿:https://www.cnblogs.com/windpoplar/p/10923830.html
2. mysql死锁问题
3. rabmq消息问题(问到mq就会问消息丢失、消息重复消费这两个问题)
-
例如消息丢失问题:具体的场景是不同环境配置了同一个mq,导致消息不知道在哪里被消费了,有时候能正常消费,有时候又消息丢失了。其他消息丢失的场景可以说使用mq的消息确认机制,来确认是否接受到这个消息 -
消息重复消费:如果是一些幂等性的操作的话,重复消费也不会有问题;另外的是通过存一个第三方id来保证消息是否被消费过(具体自己查询相关文章吧) https://blog.csdn.net/qq_41864967/article/details/90442085 -
哪些场景用到了:可以说例如订单创建成功,异步发送微信通知给用户;还有订单5分钟自动退款(rabmq的延期队列,是通过自带的插件生成的)
5. mysql慢查询的问题
- 这个具体自己编了,可以说订单表数据量很大,几千万上亿条,然后表设计又不合理,只能通过三表联查才能查询到数据,这个时候能做的就是说加查询条件才能查询数据,其他时候不让用户去查询数据。主要就是说这个上线了,各种优化都没办法进行下去等等。还有做了分表操作,运维按照数据大小,使用时间来区分表数据,然后他就会问你怎么分表,这个我不知道。
- 如果你说mysql相关的问题,他就会问mysql 的一些优化点。这个可以先从mysql 表设计讲,说尽量合理,分附属表等等,然后就是从索引方面来讲怎么加好,最后就说查询语句怎么才能用到索引等等。三个方面
三、笔试题
1. String StringBuild SttringBuff 三个区别
这个比较简单
2. 接口和抽象类的区别
笔试题的话,写的话写出重点就行了,不需要写很多
https://zhuanlan.zhihu.com/p/94770324
3. 类的加载顺序(这段屡清楚了就没啥问题了)
public class Test9 {
public static void main(String[] args) {
new B();
}
}
class A {
static {
System.out.println("静态代码块A");
}
{
System.out.println("代码块A");
}
public A() {
System.out.println("构造方法A");
}
}
class B extends A {
static {
System.out.println("静态代码块B");
}
{
System.out.println("代码块B");
}
public B() {
System.out.println("构造方法B");
}
}
输出:
静态代码块A
静态代码块B
代码块A
构造方法A
代码块B
构造方法B
5. 对象的引用和修改(这段屡清楚了就没啥问题了)
public class test2 {
public static void main(String[] args) {
test2 test2 = new test2();
Integer[] integers = new Integer[1];
integers[0] = 1;
String str = "a";
test2.aaa(str, integers);
System.out.println(str);
System.out.println(integers[0]);
}
public void aaa(String str, Integer[] integers) {
str = "b";
integers[0] = 2;
System.out.println(str);
System.out.println(integers[0]);
}
}
输出:
b
2
a
2
|