(微信java面试攻略04)
1、Kafka保证消息不重复消费
一般是在消息消费的时候做幂等性处理。
常见的方案如下:
1)利用数据库的唯一约束实现幂等
2)为更新的数据设置前置条件(CAS)
3)记录并检查操作(在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置为已消费。)

2、Kafka的消息是有序的吗?
在同一个partition里的消息是有序的,不同partition之间的消息是没法保证全局有序的。

3、使用Kafka,如果保证消息消费的顺序性?
一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。
写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。
4、Redis集群在查找key的时候,是如何路由的?
使用crc16算法对key进行hash
将hash值对16384取模,得到具体的槽位
根据节点和槽位的映射信息(与集群建立连接后,客户端可以取得槽位映射信息),找到具体的节点地址
去具体的节点找key
如果key不在这个节点上,则redis集群会返回moved指令,加上新的节点地址给客户端,同时,客户端会刷新本地的节点槽位映射关系。
如果槽位正在迁移中,那么redis集群会返回asking指令给客户端,这是临时纠正,客户端不会刷新本地的节点槽位映射关系。

5、一致性哈希算法
一致性哈希负载均衡算法的探讨

6、Redis淘汰策略
Redis过期–淘汰机制的解析和内存占用过高的解决方案

7、Redis延时队列
这是一个开放性题目,没有标准答案,只要能自圆其说,都可以。以下方案仅供参考。
数据结构使用Zset,其中member是任务描述,score是执行时间。
然后用一个定时器定时去扫这个Zset,如果有score小于当前时间戳的,说明到了执行时间了,于是就执行这个任务。然后,还要处理好并发的问题。

8、innodb的表如果没有设置主键的话,内部会怎么处理?
如果innodb的表没有设置主键的话,innodb会优先使用用户自定义主键作为主键,如果用户没有定义主键,则选取一个Unique键作为主键,如果表中连Unique键都没有定义的话,则InnoDB会为表默认添加一个名为row_id的隐藏列作为主键。

延伸问题:Innodb为什么一定需要主键?(从聚簇索引的角度去思考)

9、什么是聚簇索引?
MySQL索引分类,90%的开发都不知道

10、myIsam里有聚簇索引吗?
没有。myIsam里的索引都是二级索引,因此myIsam里索引跟数据是分开存储的。

11、synchronized底层是怎么实现的?
在 Java 中每个对象都隐式包含一个 monitor(监视器)对象,加锁的过程其实就是竞争 monitor 的过程,当线程进入字节码 monitorenter 指令之后,线程将持有 monitor 对象,执行 monitorexit 时释放 monitor 对象,当其他线程没有拿到 monitor 对象时,则需要阻塞等待获取该对象。

延伸问题:synchronized锁升级过程?Java对象的内存布局?

12、volatile的理解
面试:Java并发之volatile我彻底懂了

13、伪共享
CPU缓存从内存读数据时,是按缓存行读取的,即使只用到一个变量,也要将整行数据进行读取,这行数据量可能包含其他变量。当多个线程同时修改同一个缓存行里的不同变量时,由于同时只能有一个线程在操作,所以相比将每个变量放到不同缓存行里,性能会有所下降。(补充:缓存一致性协议)
伪共享出现的原因:因为CPU缓存和内存交换数据的单位是缓存行,而同一个缓存行里的多个变量不能同时被多个线程修改
如何避免伪共享:字节填充(创建变量时,使用字段对其进行填充,避免多个变量被分派到同一个缓存行里)

14、TCP keepalive机制
聊聊 TCP 长连接和心跳那些事

延伸问题:HTTP的keepalive

15、SYN Flood
“首包丢弃”防御SYN Flood攻击的基本原理解析

16、TCP粘包拆包
粘包拆包,Netty及远洋通信中的解决方案!超实用

17、服务端推送涉及的技术
几种服务端推送技术方案的比较

18、多路复用
I/O 模型如何演进及 I/O 多路复用是什么?