一面 315 电话 25min
项目:seata的TCC模式,redis事务,多级缓存一致性问题,guava cache和redis,shardingshpere分库分表
redis内存淘汰策略
java死锁?怎么避免?
synchronized和reenteantlock区别
hashmap
mysql索引结构,建索引注意事项,优化sql,执行计划,聚集和非聚集索引,分区
jvm内存结构
tcp和udp
拥塞控制
反问
(总结:知识点广泛,不深入追问)

二面 325 视频 65min
项目一:开发流程
项目二:下单怎么防止超卖,怎么做的服务熔断和降级
线程生命周期状态,线程池参数
sleep和wait区别
rocketmq底层实现
一个宽表,你怎么优化,宽表排序怎么处理
shardingshere底层实现?你来设计的话怎么做?
垂直水平分库分表
设计模式,详细讲了单例模式
手撕:选猴王(约瑟夫)
怎么去学习新技术的?有写博客习惯吗?
(总结:面试官挺好的,手撕没全过,赶时间去面其他公司,没时间调试和反问,晚上官网更新通过了)

seata的TCC模式

一个典型的分布式事务过程(1+3)

TransactionID:全局唯一的事务IDTC(全局事务协调者):维护全局和分支事务的状态,驱动全局事务提交或回滚
TM(事务管理器):事务的发起方标注了@GlobalTransaction。定义全局事务的范围——开始全局事务、提交或回滚全局事务
RM(资源管理器):事务的参与方式。管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

过程

  1. TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
  2. XID在微服务调用链路的上下文中传播;
  3. RM向TC注册分支事务,将其纳入XID对应事务的管辖;
  4. TM向TC发起针对XID的全局提交或回滚决议;
  5. TC调度XID下管辖的全部分支事务完成提交或回滚请求

    两阶段提交协议

    事务管理器分两个阶段来协调资源管理器,第一阶段准备资源,也就是预留事务所需的资源,如果每个资源管理器都资源预留成功,则进行第二阶段资源提交,否则协调资源管理器回滚资源。

TCC(Try-Confirm-Cancel)

实际上是服务化的两阶段提交协议,业务开发者需要实现这三个服务接口,第一阶段服务由业务代码编排来调用 Try 接口进行资源预留,所有参与者的 Try 接口都成功了,事务管理器会提交事务,并调用每个参与者的 Confirm 接口真正提交业务操作,否则调用每个参与者的 Cancel 接口回滚事务。

redis事务

muti exec discard watch unwatch

多级缓存一致性问题

答一:
首先,我们可以按照预计的热点key对系统进行缓存预热,全量同步数据到缓存系统。接着,在需要更新缓存的时候,我们可以采用增量同步的方式更新缓存。比如我们可以使用阿里Canal框架同步binlog的方式进行数据的同步。
答二:
这个问题和SMP中的缓存一致性问题差不多
可以去参考下AMD的MOESI协议或是intel的MESIF协议

答三:
无外乎两种策略

  1. 二级缓存更新后广播消息通知一级缓存哪些数据已经失效
  2. 为二级缓存数据设计一个版本号,一级缓存在访问数据之前,和二级缓存中数据版本号比较,决定是否更新

    多核CPU多级缓存一致性协议MESI

    多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱

MESI 是指4种状态的首字母。每个Cache line有4个状态,可用2个bit表示,即:

状态 描述 监听任务
M 修改 (Modified) 该Cache line有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。 缓存行必须时刻监听所有试图读该缓存行相对就主存的操作,这种操作必须在缓存将该缓存行写回主存并将状态变成S(共享)状态之前被延迟执行。
E 独享、互斥 (Exclusive) 该Cache line有效,数据和内存中的数据一致,数据只存在于本Cache中。 缓存行也必须监听其它缓存读主存中该缓存行的操作,一旦有这种操作,该缓存行需要变成S(共享)状态。
S 共享 (Shared) 该Cache line有效,数据和内存中的数据一致,数据存在于很多Cache中。 缓存行也必须监听其它缓存使该缓存行无效或者独享该缓存行的请求,并将该缓存行变成无效(Invalid)。
I 无效 (Invalid) 该Cache line无效。

多核缓存协同操作

假设有三个CPU A、B、C,对应三个缓存分别是cache a、b、 c。在主内存中定义了x的引用值为0。

双核读取

那么执行流程是:
CPU A发出了一条指令,从主内存中读取x。
CPU A从主内存通过bus读取到 cache a中并将该cache line 设置为E状态。
CPU B发出了一条指令,从主内存中读取x。
CPU B试图从主内存中读取x时,CPU A检测到了地址冲突。这时CPU A对相关数据做出响应。此时x 存储于cache a和cache b中,x在chche a和cache b中都被设置为S状态(共享)。

修改数据

那么执行流程是:
CPU A 计算完成后发指令需要修改x.
CPU A 将x设置为M状态(修改)并通知缓存了x的CPU B, CPU B将本地cache b中的x设置为I状态(无效)
CPU A 对x进行赋值。

同步数据

那么执行流程是:
CPU B 发出了要读取x的指令。
CPU B 通知CPU A,CPU A将修改后的数据同步到主内存时cache a 修改为E(独享)
CPU A同步CPU B的x,将cache a和同步后cache b中的x设置为S状态(共享)。

最终一致性解决方案

最终一致性方案的解决方案有很多,比如paxos,raft,TCC以及消息通知

消息通知 借助Kafka使用本地事务:分布式服务系统有一个共用的消息表,通过它来协调监控服务双方的业务执行状况,最终异步确保。