Java场景化面试宝典
2021-08-09 00:33:00 0 举报
AI智能生成
java进阶面试题,实际场景问题解决方案,高级程序员必知必会问题。
作者其他创作
大纲/内容
性能调优
系统调优
SQL调优
JVM调优
redis缓存
数据存入缓存
首页
banner
List集合
三个豆腐块
List集合
为你推荐条件
List集合
竞拍大厅
筛选条件
骨架星级
Hash表
注册地
Hash表
车龄
Hash表
里程
Hash表
车辆级别
Hash表
排放标准
Hash表
车源属性
Hash表
燃料类型
Hash表
查询条件
场次
Hash表
拍场模式
Hash表
所有品牌车系
List集合
热门品牌
Hash表
业务城市数据
List集合
查询结果集
为你推荐
通过zset排序用户出价的品牌车系;每次出价的时候异步去更新redis的记录以及数据库
心愿单
心愿单的查询条件
车源id存放在Zset缓存,从缓存中拿到车源id;再去ES中获取数据;
我的出价
一个月前未中标
车源id存放在Zset缓存,从缓存中拿到车源id;再去ES中获取数据;
近一个月未中标
车源id存放在Zset缓存,从缓存中拿到车源id;再去ES中获取数据;
交易失败
车源id存放在Zset缓存,从缓存中拿到车源id;再去ES中获取数据;
交易成功
车源id存放在Zset缓存,从缓存中拿到车源id;再去ES中获取数据;
我的账户
账户余额
String
保证金
String
出价次数
String
INCR
做自增操作
关注次数
String
INCR
做自增操作
加密算法
不可逆加密
加密方式
MD5
概述
信息摘要算法5
特点
单向不可逆,无法解密
产生一个固定长度的散列码
使用场景
密码存储
信息完成性校验
HMAC系列
概述
散列消息鉴别码
特点
SHA系列
特点
单向不可逆,无法解密
产生一个固定长度的散列码
使用场景
密码存储
信息完成性校验
不可逆特点
单向不可逆,无法解密
产生一个固定长度的散列码
可逆加密
非对称加密
概述
公钥加密,私钥解密
非对称加密方式
RSA
DSA/DSS
特点
1.比对称加密更加安全可靠;
2.加密解密比对称加密慢很多
使用场景
HTTPS建立SSL连接中有一个步骤就是,将服务端的公钥加密用于对称加密的密钥;也就是把数据传输的对称加密的密钥发送给服务端,这样客户端和服务端都知道了实际做数据传输的对称密钥了
对称加密
概述
加密解密都是用的同一个密钥
对称加密方式
DES
3DES
AES
特点
1.加密解密速度快;
2.适用于大量数据加密
3.由于需要把密钥传递给需要用的对接方,在传递的密钥的过程中容易被人抓包,造成数据不安全;
场景
HTTPS建立SSL连接之后,客户端和服务端使用的就是对称加密来传输数据;主要就是利用对称加密解密速度快的优势
对称/非对称加密区别
性能
对称加密性能高于非对称加密
安全性
非对称加密安全性比对称加密安全性高
加密解密方式
对称加密,加密解密都是用的同一个密钥;非对称加密,加密解密密钥是分开的;
可逆/不可逆区别
可逆:可以通过解密的密钥获取到加密之前的数据;不可逆:数据是没有办法做解密操作,无法拿到解密之前的数据;
加密盐
作用
增加数据被破解的难度
让相同的数据在被加密之后显示的数据是不一样的;
接口幂等性
查询和修改操作都是幂等;添加和删除不是幂等
分布式环境下怎么保证接口的幂等性
幂等性概述
1.用户对于同一操作发起的一次请求或者多次请求结果都是一样。
具体操作
查询操作
天然幂等的
删除操作
删除一次和删除多次可能返回的数据不是一样
更新操作
如果把某个字段的值设置为1,那么不管多少次都是幂等
如果把某个字段值加1,那么就不是幂等
添加操作
重复提交会有幂等性问题
幂等性解决方案
1.通过代码逻辑判断实现
一般场景:代码中通过代码逻辑判断
支付场景:通过唯一的订单id来判断重复
2.使用token机制实现
支付场景:页面跳转的时候获取全局唯一的token,把token缓存起来;等到提交到后台的时候,再校验token是否存在,第一次提交成功就会删除token
使用场景:分布式环境
3.乐观锁
分布式环境中,做重复校验,直接用乐观锁实现
使用场景:分布式环境
分布式系统问题
单点登录
全局唯一id生成
分布式Id要求
全局唯一
全局业务中必须要是唯一
趋势递增
这个id最好是能递增
高性能
高可用
接入方便
全局唯一id生成方式
UUID
优点
简单
无网路消耗
缺点
无业务意义
不是递增
存储消息空间大
UUID作为数据库主键,性能低下
使用场景
数据库实现方式
数据库自增id
方式概述
获取数据库自增的主键作为全局ID
优点
实现简单
id是递增
数值类型查询速度快
缺点
如果数据是单节点,无法完全保证数据的高可以用
数据库多主模式
方式概述
给几台数据库服务器自增时候设置相应的步长(比如说,自增3,自增4),获取到自增id
优点
解决单节点,并不能高可用问题
缺点
不利于后续扩容
号段模式
方式概述
从数据库批量获取自增ID
优点
批量减少数据库压力
号段方式是推荐的使用方式
ZK
实现概述
通过node节点版本生成序列号
可以生成32位,64位
redis
实现概述
利用的incr命令实现原子的自增
雪花算法
实现概述
正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。
百度uid-generator
和雪花算法类似
优点
可自定义时间戳,机器ID,序列号
美团Leaf
同时支持号段模式,雪花算法模式,可以切换
滴滴(Tinyid)
号段模式的实现
分布式锁
数据库乐观锁
操作步骤
1.先去查询数据是否存在
2.在做更新的时候对比当前数据的版本是否和第一次查询的时候版本号一致,一致才更新;
原理
基于第一次查询和第二次做修改时候查询的数据来判断中间的数据有没有被修改过
Redis分布式锁
使用redisson连接方式
操作步骤
1.在try catch外面获取锁
通过RedisClient对象获取到RedissionLock对象
2.在try catch中加锁
通过RedissionLock对象进行加锁
分支主题
3.在finally里面解锁(防止死锁,解不了锁)
原理
因为redis的crud都是单线程的,通过想Redis中设置key,value的方式
设置成功,说明当前就获取到了Redis的锁
设置失败,说明其他请求已经向Redis中设置过了当前值,其他线程获取到了锁,当前线程会阻塞等待获取锁;
Lua脚本加锁过程
1.先判断key是否存在,不存在才会加锁;
2.如果key存在,那么通过lua脚本判断,获取锁的客户端id是否和当前客户端的id相同,也就是进行可重入判断;
3.如果客户端id也不一样,那么会返回一个当前获取锁需要等待的时间,并且进入while死循环中等待获取锁;
ZK分布式锁
操作步骤
1.通过zkClient对象创建临时节点,作为加锁
2.通过zkClient对象删除临时节点,作为解锁
原理
1.zk是不允许创建相同的临时节点
2.如果zkclient对象发现已经相同的临时节点已经存在了,那么就会阻塞被阻塞;
3.阻塞实际上就是等待创建了这个节点的客户端去删除这个临时节点;
4.阻塞结束之后,创建临时节点,就获取到了锁
本质
zk不允许重复创建临时节点
有创建临时节点,就会客户端就会被阻塞
分布式事物
分布式事物概述
CAP
Consistency
强一致性
Availability
可用性
Partition tolerance
分区容错性
CAP只能保证两点
这个理论中的一致性指强一致性,而不是弱一致性
CAP选择
一般情况下保证AP和最终一致性
金融业,CA,强一致性+可用性
seata解决方案
集成了4中分布式事物解决方案
AT 模式、TCC 模式、Saga 模式和 XA 模式
分布式事物模型
AT模式
AT模式概述
对代码无侵入性的分布式解决方案
使用场景
同一项目调用两个处于不同服务上的微服务修改接口
特点
事物的第一阶段其实已经提交了;事物的回滚操作是在原来正向操作的基础上做的一个逆向操作,这个逆向操作seata已经帮你做了;
原来的一个insert操作变成delete操作;delete操作变成insert操作;update修改操作会修改回来;
解决方案
seata
TCC模式
TCC概述
事物3个操作
Try
预留业务资源
Confirm
确认执行提交事物
Cancel
执行事物回滚
TCC可以分成两个阶段
资源预留阶段
事物提交阶段/事物回滚阶段
TCC事物实现方式
Hmily轻量级分布式事务的框架, 无需搭建Hmily服务器
需要标记Try,confirm,cancel方法
Seata
ByteTCC
EasvTransaction
Saga模式
使用场景
流程比较长且只需要保证事物最终一致性的长事物解决方案
事物的参与者是其他公司的服务
特点
每个事物都有其正向的操作和逆向的事物回滚操作
正向服务,逆向补偿服务都是开发者来实现的,对业务造成了很大的侵入性
优缺点
优点
第一阶段已经提交了事物,性能比较高;
事物回滚操作基于时间异步执行,效率高;
逆向补偿服务,易于理解,易于实现;
缺点
事物在第一阶段已经提交了,也就是没有预留动作保证隔离性。
实现方式
最大努力通知
使用场景
给调用提供一个接口给被调用方回调,用来不断的通知调用方,被调用者这边是否执行结果
消息队列通知
使用场景
公司内部系统直接相互推送某个事物是否执行成功;相当于给其他系统通知这个事物是否成功。
finnally里面做事物回滚
使用场景
当前系统调用了内部的多个数据库,或者是多个服务,在调用方这边直接做数据回滚;
XA模式
理论基础
2PC协议
第一阶段每个事物完成预提交并通知把结果告诉事物协调器;事物协调器等所有分支事物都操作完成,预提交之后;第二阶段协调器通知每个事物进行逐步的提交或者是逐步的回滚操作;
二阶段详细过程
准备阶段
事物协调器向所有的事物发起者询问是否可以执行提交操作,并等待各个参与者节点的响应
参与者节点执行询问发起为止的所有事物操作,并记录到redo,undo日志中;
事物的各个参与者对事务管理器响应自己的事物是执行成功还是执行失败;
提交阶段
协调者只要收到一个事物失败或者超时,那么就会给每一个参与者发送回滚消息否则发送提交消息;
实现原理
mysql oracle等关系型数据都是支持两阶段提交协议的,也就是有一个支持多个多个事物的接口;
两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做)
使用场景
同一项目中直连两个数据库,做修改操作
解决方案
AtomMikos
使用方式
springBoot整合atomikos
<!-- atomikos 多数据源管理 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jta-atomikos</artifactId></dependency>
spring整合atomikos
<dependency><groupId>com.atomikos</groupId><artifactId>transactions-jdbc</artifactId><version>4.0.6</version></dependency>
无整合开发
<dependency><groupId>com.atomikos</groupId><artifactId>transactions-jdbc</artifactId><version>4.0.6</version></dependency>
事物过程
第一阶段每个事物完成预提交并通知把结果告诉事物协调器;事物协调器等所有分支事物都操作完成,预提交之后;第二阶段协调器通知每个事物进行逐步的提交或者是逐步的回滚操作;
特点
事物粒度大,高并发环境下,系统可用性比较低
分布式缓存
Redis与MemCache的区别
线程操作
redis数据处理是单线程,memcache是多线程处理
数据结构
Redis支持更多更复杂的数据结构,memcache只支持keyvalue的字符串数据;
数据安全性
Redis支持数据的持久化,会把数据同步到磁盘上;memcache不支持数据的持久化
数据备份
Redis支持数据备份,需要开启主从模式;memcache不支持数据备份
过期策略
REDIS支持更多的过期策略;memcache支持的过期策略少
分布式定时任务
微服务项目
模块拆分方式
1.按照不同的业务划分不同的项目
2.同一业务下不同的功能划分
Job
同一业务下的定时任务模块
获取本业务数据
直接查询属于本业务的库
直接调用本业务的原子微服务
直接调用本服务的非原子微服务
获取其他业务数据
1.调用其他原子的微服务
2.调用其他服务的非原子微服务
MQ
同一业务下消息队列模块
获取本业务数据
直接查询属于本业务的库
直接调用本业务的原子微服务
直接调用本服务的非原子微服务
获取其他业务数据
1.调用其他原子的微服务
2.调用其他服务的非原子微服务
web
同一业务下pc端接口
获取本业务数据
直接查询属于本业务的库
直接调用本业务的原子微服务
直接调用本服务的非原子微服务
获取其他业务数据
1.调用其他原子的微服务
2.调用其他服务的非原子微服务
App
同一业务下对APP接口
获取本业务数据
直接查询属于本业务的库
直接调用本业务的原子微服务
直接调用本服务的非原子微服务
获取其他业务数据
1.调用其他原子的微服务
2.调用其他服务的非原子微服务
Ms
同一业务下原子的微服务接口
Api
同一业务下非原子的微服务接口
可以聚合其他业务的原子的微服务接口
延时任务
redis
实现方式
通过Redis的key的事件通知机制
缺点
Redis的事件通知,消息只会发送一次,不管客户端是否有收到(无消息确认机制)
使用场景
需要对某些key的改变做监控
消息队列
RocketMQ
RocketMQ设置固定延时时间发送消息
缺点
延时的消息时间只能是十几个固定的延时时间
使用场景
RabbitMQ
实现方式
1.正常队列不设置消费者,给单个消息设置超时时间;
2.设置死信队列和死信队列的消费者,把超时未发送的消息发送到死信队列;
使用场景
kafka
实现方式
时间轮定时任务
使用场景
定时任务
实现方式
先对数据先进行落库,再对数据库进行定时轮询
缺点
对数据库压力大
使用场景
java延时队列
实现方式
实现Java的延时队列,这是固定的延时时间;
高并发问题
接口限流
限流方式
验证码
使用场景
容器限流
NGINX
Tomcat
队列
手动控制某些接口访问
gateway
使用场景
服务器限流
Semaphore类控制并发访问数量
任务线程池控制方式
锁
限流算法
令牌桶
实现
使用场景
漏斗桶
实现
使用场景
滑动窗口
实现
使用场景
计数器
实现
使用场景
子主题 5
流量计算方式
滑动窗口
子主题 2
子主题 3
秒杀系统设计
秒杀系统的特点及对应解决方式
1.读多写少
缓存
2.高并发
限流
负载均衡
缓存
异步
队列
3.资源访问冲突
不同层级对应解决方案
应用层
控制方式
按钮控制
点击之后,一段时间之后才能再次被点击
验证码控制
需要收到验证码才能点击
控制目的
降低用户秒杀系统的点击频率
网络层
CDN
负载层
负载均衡,反向代理,限流
降低服务器访问压力
服务层
缓存,异步,队列,限流,原子操作
降低对数据库的压力
数据库
乐观锁,悲观锁
CDN作用
lua脚本为啥可以原子性执行
0 条评论
下一页