面试官你好 我叫xxx 22年毕业于xx计算机系,在校期间考了软考中级证书, 有springboot,mybatis,springcloud等技术经验。在最近的项目是公司内部运维系统,用的是springboot开发, 数据库有mysql,redis,消息中间件rabbitmq,这个项目除了coding外,还有进行需求讨论,跟踪bug等工作。
因为公司项目比较多,所以每次沟通不及时,发布比较不方便,所以应领导要求做了这个系统。项目人员大概5个人,项目主要用git管理代码,jira管理bug和task,jenkins发布,由于项目有时候需求比较紧,就通过加班等手段保证正常上线。
自我介绍
其他人整理的面试集合
程序员追风
java3y
3y
javaguide
redis面试题
面试题
比较杂的面试题
select语句会发生什么
分布式事务
2pc,tcc
反射的应用
为何要使用Elasticsearch?
Elasticsearch是一个分布式搜索引擎。
为什么要使用RabbitMQ?
1.流量消峰
举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
2.应用解耦
以电商应用为例,应用中有订单系统、库存系统、物流系统、
支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。
在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,中单用户感受不到物流系统的故障,提升系统的可用性。
3.异步处理
有些服务间调用是异步的,
例如A调用B,B需要花费很长时间执行,但是A需要知道B什么时候可以执行完,以前一般有两种方式,A过一段时间去调用B的查询api查询。或者A提供一个callback api,B执行完之后用
api通知A服务。这两种方式都不是很优雅,使用消息总线,可以很方便解决这个问题,A调用B服务后,只需要监听B处理完成的消息,当B处理完成后,会发送一条消息给MQ,MQ会将此消息转发给A服务。这样A服务既不用循环调用B的查询api,
也不用提供callback api。同样B服务也不用做这些操作。A服务还能及时的得到异步处理成功的消息。
rabbit延时队列插件
为什么使用mongodb?作用?
主要用来应对三高问题
高并发读写
高效率存储访问
高可扩展,高可用性
传统的关系型数据库(如MySQL),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。
解释:“三高”需求:
• High performance - 对数据库高并发读写的需求。
• Huge Storage - 对海量数据的高效率存储和访问的需求。
• High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。
而MongoDB可应对“三高”需求。
具体的应用场景如:
1)社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
2)游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
3)物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将
订单所有的变更读取出来。
4)物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
5)视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。
这些应用场景中,数据操作方面的共同特点是:
(1)数据量大
(2)写入操作频繁(读写都很频繁)
(3)价值较低的数据,对事务性要求不高
对于这样的数据,我们更适合使用MongoDB来实现数据的存储。
什么时候选择MongoDB
在架构选型上,除了上述的三个特点外,如果你还犹豫是否要选择它?可以考虑以下的一些问题:
应用不需要事务及复杂 join 支持
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以)
应用需要TB甚至 PB 级别数据存储
应用发展迅速,需要能快速水平扩展
应用要求存储的数据不丢失
应用需要99.999%高可用
应用需要大量的地理位置查询、文本查询
如果上述有1个符合,可以考虑 MongoDB,2个及以上的符合,选择 MongoDB 绝不会后悔。
思考:如果用MySQL呢?
答:相对MySQL,可以以更低的成本解决问题(包括学习、开发、运维等成本)
1.2 MongoDB简介SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
嵌入文档 MongoDB通过嵌入式文档来替代多表连接
primary key primary key 主键,MongoDB自动将_id字段设置为主键
MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认
为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
自己的面试题
网络
用户在浏览器输入 URL 回车后,会发生什么?
极简面试版——说说ThreadLocal?
是什么?
Thread是java中的一个类,它让每个线程都有属于自己的变量副本,从而避免的线程安全问题。
使用方法?
ThreadLocal的使用通过set来设置当前线程的变量值,get来获取即可。
原理?
ThreadLocal是通过threadLocalMap来实现的,当我们调用threadLocal的set方法时,实际是通过threadLocalMap来存储键值对,其中键是当前ThreadLocal对象,值是我们设置的变量值。调用get方法时就是通过键来获取值。
优缺点?
优点:
1.每个线程都有自己的变量副本,避免线程安全问题;
2.易用
缺点:
1.如果没有及时清理变量副本,可能会导致内存泄漏
2.ThreadLocal的使用会导致上下文切换的开销增加。
第三次握手可以携带数据
遇到过什么问题
我们当时项目采用的是分布式系统,对生成的id有要求,所以综合考虑采用了雪花算法生成id,但是有一天开始报错,报生成的id重复,就觉得奇怪,雪花算法怎么会id重复,后面经过一系列的查找,发现是服务器时钟回拨导致的id重复
雪花算法
设计模式
Sharding-JDBC 实战(史上最全)
rabbitmq
重复消费
在消费端保证消息的幂等性,也就是任意多次执行所产生的影响均与一次执行的影响相同。
比如说,通过数据库的唯一键实现。
再比如说全局唯一id
再比如说给消息带上活属性数据,加一个version字段,每次消费更新的时候需要比较当前数据和消息中的版本号是否一致
消息丢失问题
生产者开启确认模式
队列持久化
消费者开启确认模式
rabbitmq做集群(镜像模式)
如何解决消息堆积问题
redis
数据库有1000万数据,Redis只能缓存20w数据如何保证Redis中的数据都是热点数据?
使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据
Redis的内存用完了会发生什么?
主要看数据淘汰策略是什么,如果是默认的配置 (noeviction 不删除任何数据),会直接报错
redis分布式锁
Redis实现分布式锁主要利用Redis的setnx命令。setnx是SETif not exists(如果不存在,则SED)的简写
Redis实现分布式锁如何合理的控制锁的有效时长?
1.根据业务执行时间预估
网络卡顿等,方案不是很靠谱
2.给锁续期
再开一个线程,监控执行,合理续期,但是自己实现太麻烦了,redisson帮我们做到了
Redis集群有哪些方案
在Redis中提供的集群方案总共有三种
主从复制
哨兵模式
分片集群
Mysql
执行一条 select 语句,期间发生了什么?
索引失效
如何定位慢查询?
1.使用工具,如Arthas、Prometheus、Skywalking
2.mysql自带慢日志
在/etc/my.cnf中配置
#开启Mysql慢日志查询
slow_query_log=1
#设置慢日志的时间为2s,如果sql语句查询超过2s,就会记录慢查询日志
long_query_time=2
answer
我们当时有的接口测试非常慢,压测结果大概5s钟,当时系统用了skywalking,可以监测出哪个接口,最终确定是sql问题,同时我们在mysql中开启了慢查询日志,我们设置的值就是2s,超过2s就记录到日志中(调试阶段,在生产一般不会开启,会损耗mysql性能)。
长版回答
那这个sql语句执行很慢,如何分析?
表数据量过大,没有加索引
采用explain获取sql执行情况
answer
可以采用MySQL自带的分析工具EXPLAIN
1.通过key和keylen检查是否命中了索引(索引本身存在是否有失效的情况)
2.通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
3.通过extra建议判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复
长版回答
什么是索引?
answer
索引是帮助mysql高效获取数据的数据结构,提高数据检索效率,降低数据排序的成本,简单来说就是创建了个数据目录。
长版回答
bin log、redo log、undo log
bin log(归档日志)是记录了除查询语句外的所有语句,用于数据备份、主从复制
binlog 有三种日志模式:
Statement(基于 SQL 语句的复制):
Row(基于行的复制)
Mixed(混合模式)
redo log(重做日志)是InnoDB特有的重做日志
主要有两部分文件组成,重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者是在磁盘中。
作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启 mysql 服务的时候,根据 redo log 进行 重做,从而达到事务的持久性这一特性。
内容:物理格式的日志,记录的是物理数据页面的修改的信息,其 redo log 是顺序写入 redo log file 的物理文件中去的。
mysql,如果每次更新操作都要写进磁盘,然后磁盘要找到对应记录,然后再更细,整个过程 io 成本、查找成本都很高。解决方案:WAL 技术(Write-Ahead Logging)。先写日志,再写磁盘。
具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log 里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。
undo log (回滚日志(记忆:假装没做日志)),记录发生错误前的数据
索引的底层数据结构了解过吗?
answer
InnoDB采用B+树
1.矮胖树,磁盘读写代价比较低
2.非叶子节点只存储指针,叶子节点存储数据
3.B+数便于扫库和区间查询,因为叶子节点是一个双向链表
长版回答
mvcc
数据库通过加锁来保证事务的隔离性,但是频繁的加锁会降低数据库的性能,所以通过mvcc多版本并发控制来解决,实现读取数据不用加锁,可以让读取数据同时修改,修改数据同时可读取。
但是注意只有在数据库隔离级别为读已提交,可重复读的情况下才适用
b树和b+树的区别
什么是聚簇索引(聚集索引),什么是非聚簇索引(非聚集索引)?
answer
聚簇索引(聚集索引):数据与索引放到一块,B+树的叶子节点保存了整行数据,有且只有一个
非聚簇索引(二级索引):数据与索引分开存储,B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚集索引
什么是回表?
answer
通过非聚集索引找到对应的主键值,到聚集索引中查找整行数据,这个过程就是回表,简单来说就是比如人员信息表中建立了姓名的索引,找到对应的叶子节点后会拿到主键id,再去走一次通过id查询
什么是覆盖索引?
answer
覆盖索引指查询使用到了索引,并且在该索引中需要返回的列已经能够全部找到,不需要回表查询
比如使用id查询,直接走聚集索引查询,一次索引扫描,直接返回数据,性能高
如果返回的列中没有创建索引,有可能会触发回表查询,所以开发过程中尽量避免使用select全部字段
长版回答
mysql超大分页怎么处理?
answer
使用覆盖索引+子查询解决
超大分页一般都是在数据量比较大时,我们使用了limit分页查询,并且需要对数据进行排序,这个时候效率就很低,我们可以采用覆盖索引和子查询来解决
先分页查询数据的id字段,确定了id之后,再用子查询来过滤,只查询这个id列表中的数据就可以了,因为查询id的时间,走的是主键索引,所以效率提升很多
长版回答
索引创建原则有哪些?
索引失效
answer
违反最左前缀法则
范围查询右边的列,不能使用索引
不要在索引列上进行运算操作
字符串不加单引号,造成索引失效
以%开头的like模糊查询,索引失效,如果只是尾部模糊匹配,索引就不会失效