面试回答
自我介绍
平时你是怎么学习的
首先是通过视频入门,视频讲解一般比较生动,有即时反馈,跟着入门不会溜神
然后就是自己再把东西梳理一遍,看下是否有遗漏或者不清楚的点。
然后是关键的点,就是去各大社区平台看技术文章,例如阿里云、腾讯云、博客园或者是一些我觉得是宝藏博主的私人blog平台,还有像公众号的文章和书籍这些,都有看,我觉得看这些文章都是很有意思,广度和深度都很不错的学习方式
一般到了这里,我基本就是能比较完善的学习了,因为我看的文章确实挺广的,然后对于一些特殊的、有意思的东西,我会自己去做实验,比如MySQL里的锁,我就有专门去手动研究测试过。
因为我看的文章广度比较大嘛,所以可能出现有些地方说法不一致的地方,这时候我就得弄清楚到底哪个是真相,这时候我会再去扩大信息来源的广度和深度,不断发掘知识,这里也会结合gpt来进行问,如果感觉还是两种说法都有,搞不清楚,我就启动我的大招,去翻源码了,我看源码的步骤是这样的,我会去问gpt,我这块内容的源码,具体是在哪,然后才去看,比如我记得用源码解决的部分就有这些情况:
- 一个是RocketMQ的消息重试那块,我们看到的常见的说法是,消息如果消费者那边没响应的话,broker会重复投递消息,会重复投递16次,但是我在一个地方看到的说法又是,如果是在顺序消费的情况下,投递次数超过了,就会丢弃这次的消息到私信队列,然后消费后面的消息,看到这里,我就想,这不就破坏消息顺序消费了吗,比如如果消息顺序是消息1,消息2这样子,消息1重复16次投递不出去,然后就跳过消息1,消费消息2,这就破坏我们说的顺序消息了啊,RocketMQ真的会这么设计吗。然后我就去翻源码进行查看,发现他在源码里面,重复次数其实设置的是-1,并不是16,然后这个字段上面有注释,注释说的是,在并发消费下,-1意味着16,在顺序消费下,-1意味着Integer.MAX_VALUE,然后我去具体的使用上看了,发现确实是会根据不同场景下是不同的重复投递次数的,那么在顺序消费下,其实他就是int的最大值,就是一直投递了,那其实就不会跳过这个消息了,这其实就是通过源码来解决我看过的文章发生冲突的一个例子吧。
- 还有一个就是我看《深入理解Java虚拟机》上面说,HotSpot新生代晋升老年代的年龄是15岁,但是如果Survivor中相同年龄所有对象大小总和大于Survivor一半,年龄大于或等于该年龄的对象就可以直接进入老年代。但是我又是在其它地方看到了另一种说法,另一种说法是说动态年龄的判断是小于或等于某个年龄的所有对象大小大于总和的一半,那么新的阈值就被设置成这个年龄。那这里其实就是两种说法,我把这两种说法都问了gpt,并让他给出源码坐标,也去源码里面看了下,发现其实是后者说法是正确的,也就是《深入理解Java虚拟机》其实在这个问题上有错,这里其实也是比较惊讶的一点,因为这个书我看了两遍,感觉真的是写JVM非常好的一本书,但真的就是突然感觉还是不能尽信书吧。
- 还比如说我在学RocketMQ事务消息的时候,就感觉这样真的能保证数据一致吗,我就去考虑极端情况,例如本地事务提交了,但是commit消息还没发送出去,此时生产者又宕机了,那么MQ也反查不到事务信息,这时候会怎样,但是网上没搜到有文章讲这种极端情况,我就去看源码了解RocketMQ是怎么解决的,通过源码我看见,MQ会起一个线程每隔30s轮询一遍事务消息进行状态回查,如果回查次数大于等于最大次数也就是15次,那就会直接丢弃这个消息到一个topic叫TRANS_CHECK_MAXTIME_TOPIC的队列中。所以其实事务消息也并不一定是安全的,也有可能导致数据不一致,但是我当时又顺便看了下它的源码中回查状态的那部分,发现它其实通过生产者组id获取生产者组实例,然后轮询选择出具体的某个实例,来进行状态回查的,也就是回查的机器和发送事务消息的机器不一定是同一个,所以我们生产者组是可以部署集群来提高可用性进而解决这个事务消息可能产生的数据不一致问题的。