主题
面试总结——交通/兴业银行
1.数据库索引
markdown
(1) 普通索引(2) 唯一索引(3) 主键索引(4) 联合索引(5) 全文索引2.抽象类和接口的区别
markdown
首先抽象类中可以有不是抽象的普通方法
而接口中默认都是抽象方法,没有方法体,就是默认用abstract关键字修饰的方法3.varchar 和 char 的区别
markdown
主要区别一 长度:
char是定长的,varchar是可变长的就是长度可变的
varchar是自定义长度的,在数据库中设置比如说varchar(10),那么超过10就取到10个字符串,不到10就用空格补
主要区别二 储存容量
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符4.Spring 和 SpringBoot 的区别
markdown
Spring 它是一个轻量级开发框架,有两大核心,使用的话需要自己去配置文件
然后SpringBoot是一个集成了很多依赖和配置的框架是一个配置化思想,把很多的东西都封装进去了,像SpringSpringMVCMybatis,而且大部分配置都已经集成好了,我们就需要简单的修改一下就行了5.消息队列,作用
markdown
项目 :rabbitmq,用作异步调用
作用: 消息队列主要有三大使用场景,分别是异步、流量削锋和应用解耦。另外还包含日志 和消息通讯
在项目中为了实现异步调用,所以采用消息队列进行服务调用6.RPC 框架理解
markdown
首先他是一个基于TCP远程调用的一个框架,代表框架有Dubbo
我的理解的话,PRC框架也是通过代理对象来调用的,与具体的协议无关,还实现了序列化
所以我觉得他的并发传输量是非常高的,但是因为实现了序列化,所以灵活度的话不如基于HTTP的远程调用7.Spring 项目的配置文件执行顺序
markdown
Spring Boot 配置文件的优先级顺序,遵循以下规则:
(1) 先加载 JAR 包外的配置文件,再加载 JAR 包内的配置文件;
(2) 先加载 config/resources 目录内的配置文件,再加载 config/resources 目录外的配置文件;
# 按文件类型
properties > yml > yaml
# 按路径分类
当前project/config > 当前project > classpath/config > classpath
# 按命令行设置
jar包外的参数 > jar包内的参数8.数据库中视图的作用,外键的作用
markdown
在视图中可以更好的看清表与表的一个关联关系还有表的大体结构,也可以分析是什么样的一个表关系,多对多一对多,我之前用的数据库可视化工具是Navicat,他里面有一个简单的视图关系表,可以看清简单的表关系
外键作为一个表的主键插入到另一张表有着关联作用,可以组成联合主键,方便多表查询9.sql 调优
slow_query_log 是否开启慢查询日志,开启 set global slow_query_log = 1
定位执行效率慢的 sql 语句
需要判断是查询多的数据库/表还是删增多的数据库/表
然后针对优化
markdown
四个点
1.最大化利用索引
1. 查询很多的表需要建立索引
2. 删增改多的表就需要考虑是否建立索引了,或者短索引
2.尽可能避免全表扫描
1. 避免使用模糊查询,必要使用要注意%号的位置
2. 避免使用in 和 not in 和 or,区域查询(< >)可以使用between替代
3. 避免使用子查询,Order By
3.减少无效数据的查询
1. 不能用,Select * from 的操作,会查询无效数据,尽量指定字段查询
2. 避免使用无效的函数
3. 避免使用Having,用Where代替
4.sql语句优化
1.优化group by语句: Mysql默认就进行了排序, 但是有时候排序并不是我们业务所需的, 额外的排序会降低效率. 所以在用的时候可以禁止排序, 使用order by null可禁用.
2.插入insert语句,使用insert语句时尽量用批量插入10.Redis 和 Memcache 的区别
markdown
Redis与Memcache的区别:Memcached仅支持简单的key-value结构的数据记录,不支持枚举,不支持持久化和复制等功能。Redis拥有更多的数据结构和并支持更丰富的数据操作,还同时提供了持久化和复制等功能。11.定时任务,分布式如何保证一致性
markdown
使用分布式锁
分布式锁大致有三种实现
1. 基于redis的分布式锁
2. 基于数据库实现分布式锁
3. 使用Zookeeper实现分布式锁12.cookies 和 session 原理
markdown
cookies是存在客户端的
当用户第一次浏览某个使用Cookie的网站时,该网站的服务器就进行如下工作:
该用户生成一个唯一的识别码(Cookie id),创建一个Cookie对象;
默认情况下它是一个会话级别的cookie,存储在浏览器的内存中,用户退出浏览器之后被删除。如果网站希望浏览器将该Cookie存储在磁盘上,则需要设置最大时效(maxAge),并给出一个以秒为单位的时间(将最大时效设为0则是命令浏览器删除该Cookie);
将Cookie放入到HTTP响应报头,将Cookie插入到一个 Set-Cookie HTTP请求报头中。
发送该HTTP响应报文。
Session是基于Cookie来实现的
不过session是存在服务端的使用的是jssessionid唯一标识13.说一下微服务
markdown
微服务(Microservices)是一种架构风格,一个大型复杂的项目,可以由多个微服务组成。
项目中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注完成自己的业务
目前的微服务架构主流是:
SpringBoot+Dubbo和SpringBoot+SpringCloud的架构模式
服务之间的调用有常见的两种:
1.RPC远程函数调用:基于TCP协议,并发能力强,代表框架为dubbo
2.HTTP请求:支持多种协议和功能,更轻量和灵活,代表SpringCloud14.数据库的中间件
markdown
360 的Atlas 是个基于 MySQL 协议的数据中间层项目,读写分离,库中负载均衡的作用
Mycat 数据库中间件,支持分布式事务,可解决分布式主键生成问题,提供一些分片策略,还能sql优化15.索引优缺点
markdown
优:
对于数据量大的表建立索引可以提高查询效率
排序和分组的字段也可以提高效率
缺:
创建索引和维护索引需要时间成本
添加索引后会降低删增改的效率
还有索引是占用物理空间的,数据量越大的表索引的占空间越大,要考虑这个物理空间的问题16.Spring 事务的传播级别
markdown
propagation传播
require必须的
suppor支持
mandatory 强制托管
requires-new 需要新建
not -supported不支持/never从不/nested嵌套的
17.如何保证 mq 消息不丢失和重复消费
markdown
丢失就是可靠性问题 mq队列生产者丢消息,消费方丢消息
1. 队列,交换机持久化,保证数据不丢失
2. 定义消息重试机制
3. 手动ack确认
重复
1.事务机制 生产者发送前开启事务机制,没有收到消息会回滚
2.保持幂等性,可利用redis来构建一个唯一id实现幂等性18.内存溢出的情况
markdown
1.项目中用到了TheadLocalMap集合,因为他底层原理的问题,使用的key是一个弱引用,可能会被GC回收,导致value不能一直存在导致内存溢出,所以这种引用问题,在使用完必须要remove清空
2.当数据库数据多的时候,一次查询大量数据可能会出现内存溢出,所以要分页查询
3.项目如果处理了死循环或者大量递归使用,也可能会导致内存溢出
4.可以设置jvm值的方法是通过-Xms(堆的最小值),-Xmx(堆的最大值),来定义内存19.项目中印象最深的问题
markdown
项目问题:
在这个模块中,我遇到了一个问题,由于发布文章模块需要远程调用其他微服务,当发布文章失败时,当前微服务的事务可以回滚,但是被远程调用的服务没法回滚,造成数据不同步的问题,最后我们就询问一些同事和查询了资料,发现是一个分布式事务的问题,从这个问题中就了解了分布式事务的概念,然后了解到了可以采用了阿里巴巴的分布式事务解决方案Seata和几种的事务解决模式20.项目中学到了什么?
markdown
通过项目呢一个是对项目整体的架构更加的熟悉,对一些中间件的使用也得到了一定程度的了解
然后最重要的是了解到了有时候自己思考的代码和实际的业务会不太一致,有时候还是得专注于业务,让技术为业务来进行一个让步21.说一下 JWT 技术
JWT 的构成:
头部 (请求头):头部信息用了这个 base64 进行了加密,是可对称的加密
playload(载荷): 这个地方就是存放一些有效信息的地方或者声明
signature(签证信息): 这个就是一个验证的字符串信息,用于检验这个 token 的,这个东西是我们后端,服务端生成的,相当于密钥,不能随意泄漏
markdown
JWT
使用base64url编码
基于token的鉴权机制类似于http协议也是无状态的
网上参照着整一个工具类生成的token
单点登录,无状态验证
jwt token 不能存放一些敏感信息,还是有泄漏的风险的
为保证安全尽量使用https协议
1. JWT token 泄露了怎么办?(常问)
使用 https 加密你的应用,返回 jwt 给客户端时设置 httpOnly=true 并且使用 cookie 而不是 LocalStorage 存储 jwt,这样可以防止 XSS 攻击和 CSRF攻击。22.项目是如何使用 redis 的,如何保证一致性?
markdown
1.redis使用
用redis里面的list数据类型来统计大量的访问量
流程:首先利用rabbitmq在用户进行互动行为的模块下进行定义发送消息的代码,每当用户进行了一次访问,或者点赞收藏等操作,就会发送一条消息,如何在数据统计模块定义监听类,监采集消息后向redis存储行为的信息,后面再使用xxljob定时统计redis中的行为数据聚合数据得到结果
2.保证xxljob调度的一致性
加分布式锁,基于redis的Redisson实现的分布式锁,具体的redis配置我这没有实际配置过,
使用的话就是redisson里面的trylock加锁命令
3.redis的一致性问题(配合事务实现命令有序性) 项目难点
因为redis的list队列中存放有大量的访问数据,我们要聚合的话就必须要多次循环取出发送大量命令,之前是使用while循环使用lpop命令取出,但是效率非常低还不能保证一致性
所以为了保证一致性,就使用的redis的管道命令,采用 redis的管道命令 Pipeline 可以一次性执行多个命令,所以可以执行lRange,lTrim的范围查询命令,后面就保证执行的性能,还能保证命令有序执行。
但是用管道命令实现确实很麻烦,后面就进行采用了更好的优化手段
就是使用lua脚本优化代码,lua脚本可以发送大量命令到redis里面,还可以配合事务实现命令有序性,但是具体的优化手段我就没有参与了23.项目的线程池如何用的?
markdown
项目是如何使用的线程池的:
这个线程池使用的是Spring框架提供的ThreadPoolTaskExecutor线程池创建的,这个线程池Spring为我们封装好了,就不直接使用JDK提供的一些线程池,之前看过阿里巴巴的开发手册,上面写了尽量不用JDK的原生Executor线程池创建,因为这样创建出来的线程池他的队列是一个无限大的队列,会导致内存浪费和溢出等问题
然后线程的核心参数就根据业务来自定义一些配置,定义一个线程池的配置类交给IOC容器管理,然后使用就往里提交任务就行了
后面还问了:核心参数,拒绝策略