[关闭]
@yexiaoqi 2022-04-12T09:50:29.000000Z 字数 9319 阅读 878

项目&技术

java面试总结


商城项目

秒杀模块

秒杀模块是如何实现的?如何解决高并发的问题?

秒杀在同一时间段会有很大的并发,对web服务器,数据库,业务代码都有要求。

商品详情模块

商品上下架后,发消息(商品的sku_id)给ActiveMQ,页面生成服务拿到id,查询数据库生成对应的静态页面,解决高并发场景中对web服务器的压力,同时用户的体验更好。

搜索模块

用户输入关键字,用solr完成搜索,返回给前端页面展示。

技术点

Dubbo

zookeeper

Redis

ActiveMQ

传递消息的方式:

  1. p2p:点对点 Queue,一对一,一条消息只做一件事,只对应一个服务
  2. pub/sub:发布订阅 Topic,一对多,一条消息会做多件事情,对应多个服务

消息队列(MQ)的作用?

主要有三点:解耦、异步、削峰

如何保证消息不丢失?

  1. 消费者收到消息了,但是处理过程出bug

    • 设置手动签收
  1. final Session session = connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);
  1. try{
  2. //1.收消息
  3. //2.处理消息
  4. //3.手动签收 message.acknowledge();
  5. }catch(){
  6. //4.选择性重发
  7. session.recover();
  8. }

几种MQ比较

ActiveMQ:最流行,但可能丢消息

RabbitMQ:基于erlang语言开发,高可用高并发,适合集群服务器。跨平台,支持多种语言,有消息确认机制和持久化机制,可靠性高。

ZeroMQ:延迟低,快

Kafka:高吞吐(10W/s),完全的分布式系统,适合处理海量数据

Solr

Solr与Elasticsearch的区别

  1. solr查询快,支持更多格式;但建立索引时,会产生IO阻塞,搜索效率下降
  2. ES建立索引快,适用于实时查询的场景,只支持json格式;ES是天生是分布式的,可以支持更大的数据量

Solr怎么设置搜索结果排名靠前?

可以设置文档中域的boost值,boost值越高计算出来的相关度得分就越高,排名就越靠前。用来把热点商品或者推广商品的排名提高。

FastDFS

FastDFS和HDFS有什么区别?

指标 适用于 文件分布 系统性能 复杂性 FUSE POSIX 备份机制 通讯协议接口 社区支持 开发语言
FastDFS 4KB~500MB 小文件合并存储,不分片 很高 简单 不支持 不支持 组内冗余备份 API HTTP 国内用户群 C
HDFS 大文件 大文件分片分块存储 简单 支持 支持 多副本 原生api 较多 java

AngularJS

四大特征:MVC模式、双向绑定、依赖注入、模块化设计

Spring Security

核心过滤器:springSecurityFilterChain

类:org.springframework.web.filter.DelegatingFilterProxy

认证管理器里配放行的用户与角色,或者指定认证类(自定义认证类时,要实现UserDetailsService接口,重写loadUserByUsername方法)


interview

项目

遇到什么问题?是怎么解决的?

问题:在处理订单时要用到定时任务,当时采用的是Spring Task来完成,由于一个订单服务会部署多个,多个订单服务同时去处理任务会造成任务被重复处理的情况,如何解决任务的重复处理。

解决:采用乐观锁解决,在任务表中设置一个version字段记录版本号,取出任务记录同时拿到任务的版本号,执行前对任务进行锁定,具体的做法是执行update根据当前版本号将版本号加1,update成功表示锁定任务成功,即可开始执行任务。

认证授权是如何实现的?

采用Spring security + Oauth2 完成用户认证及用户授权,认证授权流程如下:
1. 用户请求身份认证服务完成身份认证
2. 认证服务下发用户身份令牌和jwt令牌,拥有身份令牌表示身份合法,jwt令牌用于完成授权
3. 用户携带jwt令牌请求资源服务
4. 网关校验用户身份令牌的合法性,不合法表示用户没有登陆,如果合法则放行继续访问
5. 资源服务获取jwt令牌,根据jwt令牌完成授权

ElasticsSearch

ElasticSearch index Type(准备废弃) Document Field Mapping
MySQL Database Table Row Column Schema

项目ES索引中有哪些字段?

  1. CREATE TABLE `course_pub` (
  2. `id` varchar(32) NOT NULL COMMENT '主键',
  3. `name` varchar(32) NOT NULL COMMENT '课程名称',
  4. `users` varchar(500) NOT NULL COMMENT '适用人群',
  5. `mt` varchar(32) NOT NULL COMMENT '大分类',
  6. `st` varchar(32) NOT NULL COMMENT '小分类',
  7. `grade` varchar(32) NOT NULL COMMENT '课程等级',
  8. `studymodel` varchar(32) NOT NULL COMMENT '学习模式',
  9. `teachmode` varchar(32) DEFAULT NULL COMMENT '教育模式',
  10. `description` text NOT NULL COMMENT '课程介绍',
  11. `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间戳logstash使用',
  12. `charge` varchar(32) NOT NULL COMMENT '收费规则,对应数据字典',
  13. `valid` varchar(32) NOT NULL COMMENT '有效性,对应数据字典',
  14. `qq` varchar(32) DEFAULT NULL COMMENT '咨询qq',
  15. `price` float(10,2) DEFAULT NULL COMMENT '价格',
  16. `price_old` float(10,2) DEFAULT NULL COMMENT '原价格',
  17. `expires` varchar(32) DEFAULT NULL COMMENT '过期时间',
  18. `start_time` varchar(32) DEFAULT NULL COMMENT '课程有效期-开始时间',
  19. `end_time` varchar(32) DEFAULT NULL COMMENT '课程有效期-结束时间',
  20. `pic` varchar(500) DEFAULT NULL COMMENT '课程图片',
  21. `teachplan` text NOT NULL COMMENT '课程计划',
  22. `pub_time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '发布时间',
  23. PRIMARY KEY (`id`)
  24. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ES ik分词器如何实现热加载?

方案一:使用官方的热更新方案,加载外部词典

  1. <!--用户可以在这里配置远程扩展字典 -->
  2. <entry key="remote_ext_dict">http://xxx.com/hot_ext.dic</entry>
  3. <!--用户可以在这里配置远程扩展停止词字典-->
  4. <entry key="remote_ext_stopwords">http://xxx.com/stopwords.dic</entry>

http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
该 http 请求返回的内容格式是一行一个分词,换行符用 \n 即可

可以将需自动更新的热词放在一个 UTF-8 编码的文件里,放在 nginx 或其他简易 http server 下,当文件修改时 http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。另外做一个工具来并更新这个文件。

缺点:据反馈可以用但不太稳定

方案二:修改 ik 分词器的源码,从mysql中加载

推荐第二种方案,不过两种方案更新词典后需要根据业务场景,看是否需要重做索引

RabbitMQ

如何保证RabbitMQ的可用性?

RabbitMQ基于主从,使用镜像集群模式,每个节点都有这个队列的完整数据,无法水平扩展,网络带宽压力比较大

如何保证消息消费幂等性?

这个一般在业务代码中保证,可以基于数据库唯一键来约束,或者消费之前先查一下,已经处理就跳过

RabbitMQ如何处理消息丢失问题?

RabbitMQ如何保证消息的顺序性?

拆分成多个队列,每个队列一个消费者。
或者就一个队列对应一个消费者,在消费者内部用内存队列排队,然后分发给底层不同的worker来处理

零拷贝

由于CPU和IO速度的差异问题,产生了DMA技术,通过DMA搬运来减少CPU的等待时间。
传统的IOread+write方式会产生2次DMA拷贝+2次CPU拷贝,同时有4次上下文切换。
而通过mmap+write方式则产生2次DMA拷贝+1次CPU拷贝,4次上下文切换,通过内存映射减少了一次CPU拷贝,可以减少内存使用,适合大文件的传输。
sendfile方式是新增的一个系统调用函数,产生2次DMA拷贝+1次CPU拷贝,但是只有2次上下文切换。因为只有一次调用,减少了上下文的切换,但是用户空间对IO数据不可见,适用于静态文件服务器。
sendfile+DMA gather方式产生2次DMA拷贝,没有CPU拷贝,而且也只有2次上下文切换。虽然极大地提升了性能,但是需要依赖新的硬件设备支持。

如何实现扫码登录功能?

扫码登录当中涉及到的三种角色:PC端、手机端、服务端。涉及到2个问题:

扫码登陆的整个流程

具体流程如下:
- 访问PC端二维码生成页面,PC端请求服务端获取二维码ID
- 服务端生成相应的二维码ID,设置二维码的过期时间,状态等
- PC获取二维码ID,生成相应的二维码并展示
- 手机端扫描二维码,获取二维码ID
- 手机端将手机端token二维码ID发送给服务端,确认登陆
- 服务端校验手机端token,根据手机端token二维码ID生成PC端token
- PC端通过轮询方式请求服务端,通过二维码ID获取二维码状态,如果已成功,返回PC端token,登陆成功

定时任务如何避免被重复调度?

就是一次调度任务只有一个机器执行,不会因为是分布式部署而出现多台机器同时执行某个job。思路是使用分布式锁

基于数据库实现分布式锁

QuartzacquireTriggersWithinLock=true获取 trigger 的时候上锁(抢占式获取数据库锁并由抢占成功的节点负责运行),默认是 false,使用乐观锁,但可能出现 ABA 导致重复调度

XXL-JOB:使用数据库悲观锁

  • setAutoCommit(false)关闭隐式自动提交
  • select lock for update显示排他锁,其他事务无法进入&无法实现for update
  • 读数据库任务信息 -> 拉任务到内存时间轮 -> 更新数据库任务信息
  • commit提交事务,同时释放for update排他锁(悲观锁)

基于缓存(redis)实现分布式锁

  1. 获取锁的时候,使用 setnx 命令设置锁、设置过期时间,value 作为一个随机字符串,解锁时用来判断
  2. 获取锁的时候,增加超时时间
  3. 解锁时通过随机字符串判断是不是同一把锁

基于 zookeeper 实现分布式锁

  1. 创建目录 mylock
  2. 线程 A 想获取锁,就在 mylock 目录下创建临时节点,会返回一个数字
  3. 获取 mylock 目录下的所有节点,获取比自己小的兄弟节点,如果不存在说明当前线程的序号最小,那么他就获取了当前这把锁
  4. 线程 B 获取所有节点,判断自己是不是最小节点,设置监听比自己小一位的节点
  5. 线程 A 处理完毕,删除自己的节点。线程 B 监听到了变更事件,判断自己是不是最小的,如果是则获取到锁

JVM 调优

什么时候考虑 JVM 调优?

JVM 调优的目标

JVM 调优量化目标

JVM 调优的步骤

  1. 分析 GC 日志及 dump 文件,判断是否需要优化,确定瓶颈问题点;

  2. 确定 JVM 调优量化目标;

  3. 确定 JVM 调优参数(根据历史 JVM 参数来调整);

  4. 依次调优内存、延迟、吞吐量等指标;

  5. 对比观察调优前后的差异;

  6. 不断分析和调整,直到找到合适的 JVM 参数配置;

  7. 找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。

常见的 JVM 参数

堆栈配置相关

垃圾收集器相关

辅助信息

常用调优策略

数据库分库分表的缺点

分布式事务如何解决?TCC?

集中解决方案:
- 2PC、3PC
- TCC(Try、Confirm、Cancel)
- 本地消息表
- 最大努力通知
- Seata 事务

TCC 的优点时可以自动逸数据库操作的粒度,降低了所冲突,可以提升性能;

TCC 的缺点时应用侵入性强,需要根据网络、系统故障等不同失败原因实现不同的回滚策略,实现难度大,一般借助 TCC 开源框架,例如 ByteTCC、TCC-transaction、Himly。

Spring事务失效的12种场景

Spring 事务:再对应service层方法上使用@Transcational,分布式的话需使用分布式事务

事务不生效

事务不回滚

其他

大事务问题:事务执行耗时比较长,会导致死锁、锁等待、回滚时间长、接口超时、并发情况下数据库连接被占满、数据库主从延迟等问题

编程式事务,基于TransactionTemplate的编程式事务优点:避免由于 Spring AOP 导致事务失效的问题、能更小粒度的控制事务的范围,更直观

  1. @Autowired
  2. private TransactionTemplate transactionTemplate;
  3. public void save(final User user) {
  4. queryData1();
  5. queryData2();
  6. transactionTemplate.execute((status) => {
  7. addData1();
  8. updateData2();
  9. return Boolean.TRUE;
  10. })
  11. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注