2.1 抛问题说答案

项目过程中你遇到了什么样的难解决问题?你是如何解决的?
什么样的问题是难解决的

  • 常见问题or偏门门问题
  • 正常问题or踩坑问题

面试官主要是想看下你做的内容的深度实操经验以及你解决问题的思考和手段

2.2 交易一致性问题

2.2.1 重复支付

  • 支付系统因为各种原因重复回调

考察点:幂等方法

普通做法
image.png

如果在一次极短时间内,回掉了了两次,都查询到为初始值,就会发货两次。

防重幂等:
防重解决方案1:悲观锁

image.png
解决方案2:乐观锁
image.png

幂等,无论是回滚还是commit都返回支付成功了
image.png

2.2.2 超时退问题

交易系统和商品库存都属于分布式的两个节点上,在回滚上,需要分布式事务。

  • 如何回滚内容
  • 回滚失败如何解决
  • 重复回滚如何预防

考察点:分布式事务,流水号应用,重试方式

分布式原理

  • CAP

一致性(Consistency) :客户端知道一系 列的操作都会同时发生(生效)
可用性(Availability) :每 个操作都必须以可预期的响应结束
分区容错性(Partition tolerance) :即使 出现单个组件无法可用,操作依然可以完成

  • Base

Basically Available (基本可用)
Soft state (软状态)
Eventually consistent (最终一致性)

2.2.3 分布式事务解决

二阶段提交(唯一一个强一致性)
异步确保型
事务型消息
TCC型

二阶段提交

单点事务
image.png

二阶段提交引入事务管理者,交易系统承担了协调的角色可以看做事务管理者,server1和server2在各自内部开启事务,执行之后,进行ack,如果server commit成功,server2没有成功,没有commit,其他客户端访问,会被阻塞住,无法查询,因为对应行或者表会上锁,性能比较低,一般很少实际会使用。
image.png

TCC协议

  • try
  • confirm
  • cancel

用到的表

交易表

id status item_ id
2020103020102 init 87

status状态分布:
init初始化
stock success 库存冻结成功
voucher
success优惠券冻结成功
paying支付中
fail支付失败待回滚
voucher_rollback 优惠券回滚成功
stock_rollback库存回滚成功

image.png

image.png

image.png

image.png

执行流程
image.png
image.png

到这里,两个try操作执行成功。try执行成功,数据库锁就释放掉了

第二步用confirm,执行log记录的修改。

如果,营销系统扣减优惠券库存不足,就要进入cancel阶段,根据分布式事务id,即XID,去做回滚操作,并且将日志中的状态改为已回滚,当然这三个阶段的操作本身都要支持幂等。通过xid确定幂等性。

confirm时要确认是否是init,如果是rollback就说明系统出来问题要人工进行排查。

如果交易系统挂了,怎么办,可以从外部引入定时器扫一些中间状态,把这些异常状态捞出来,状态停留超过十五分钟。
因为交易是用户触发的,去回滚库存和回滚优惠券,定时任务就是来回滚的。

读写数量问题

随机连接zookeeper,发起了写请求,将对应数据写到leader当中,sync给对应的follower。
image.png

sync有三种选择
1、异步同步,效率高,不需要等待同步,follwer读到的可能就是旧的数据,整个集群没办法保证强一致(这里只是假设,实际上zookeeper不是这样的)这样只能保证最终一致性的。

2、同步同步
都收到了follower的ack,强制要求所有follower节点都写成功才算成功。leader节点作为事务协调者。这种机制需要配合二阶段提交,才能保证强一致性。

raft同步
写对象,同步超过一半以上被同步完就可以,三个节点同步两个,就算作成功了。外加二阶段提交。超过一半同步成功可以进行投票,来选出一个数据最新的节点会作为一个新的节点。

异步确保型

采用异步消息的方式确保事务可以最终一-致
交易表
fail支付失败待回滚
voucher back 优惠券退成功
stock
back 优惠券退成功
流水表
加入back状态

image.png

支付系统支付失败通知,将库存进行回滚回退,回滚优惠券,通过状态判断和xid做幂等。

事务型消息

使用事务型消息确保发送方的落地能力。

上面异步确保型,无法确保消息投递成功,如果事务提交了,但是投递消息失败了,或者事务没有提交,但是消息投递了。

rocketmq在kafka基础上加入了事务型消息的保障。

rocketmq会将prepare消息持久化到磁盘,等本地事务commit之后,才会真正执行send commit消息,才会做真正的消息投递,如果本地事务执行失败,就会send rollback给消息中间件,就不会讲消息投递出去,如果send commit一直发送不出去,消息中间件会定时回查,可以回查消息发送方,把prepare id带给发出prepare的系统,去查本地事务的状态,如果本地事务没有执行成功是支付中状态,可以告诉过一会来查询,如果本地事务执行失败产生rollback,会rollback消息中间件的prepare。第三种情况,xid已经成功更新状态,表示send commit没有发送成功,可以将prepare消息进行commit。

事务型消息机制,就是利用rq事务反查机制,确定会commit或rollback,来保证最终一致性。

2.3 面试官提问

2.3.1 你有没有遇到java程序崩溃的问题,如何做排查?

通用jvm工具

  • jps:虚拟机进程状态工具

示例: jps -v | grep pid

  • jinfo: jvm参数信息工具

示例: jinfo -flags pid

  • jstat: 查看虚拟机各种运算状态

示例: jstat -gcutil pid

jstat各种参数表示什么
S0:新生代中Survjvor space 0区已使用空间的百分比
S1:新生代中Survivor space 1区已使用空间的百分比
E:新生代已使用空间的百分比
O:老年代已使用空间的百分比
M:元数据区已使用空间的百分比
CCS:压缩类空间利用率百分比
YGC:从应用程序启动到当前,发生Yang GC的次数
YGCT:从应用程序启动到当前,YangGC所用的时间[单位秒]
FGC:从应用程序启动到当前,发生Full GC的次数
FGCT:从应用程序启动到当前,FullGC所用的时间
GCT:从应用程序启动到当前,用于垃圾回收的总时间[单位秒]

  • jstack: 线程快照工具.

示例: jstack -l pid

  • jmap: HeapDump工具

示例:
jmap -heap pid查看堆信息
jmap -dump:format=b,file=heapDump.hprof pid导出堆文件并用jhat查看
jhat -port 8899 heapDump.hprof
浏览器访问:http://ip:8899

线上OOM问题排查
下面的配置表示,当内存溢出的时候保存堆区快照。

java -Xms48m -Xmx48m -XX:+HeapDumpOnOutOfMemoryError
XX:HeapDumpPath=./heapdump.hprof -jar mianshi.jar

使用jprofiler查看dump文件及call tree分析
image.png

2.3 你有什么问题吗?

  • 背景:一面的面试官和你职级相同
  • 信息了解:最好的了解实际工作内容和细节的机会
  • 坦诚表现:对岗位的表现浓厚兴趣

2.4 一面雷点

避免踩坑

  • 一定要准备的很清晰,不能在项目结构上有盲点,否则容易被深问
  • 不是自己负责的部分要么就弄清楚,要么就直接说不清楚