Java工程师面试: 这些高命中率面试题你会么?

HTTP和HTTPS的区别


ssL(Security Sockets Layer,安全套接层)
>为网络通信提供安全及数据完整性的一种安全协议
>是操作系统对外的API,SSL3.0后更名为TLS
>采用身份验证和数据加密保证网络通信的安全和数据的完整性

>HTTPS需要到CA申请证书,HTTP不需要
>HTTPS密文传输,HTTP明文传输
> HTTPS=HTTP+加密+认证+完整性保护,较HTTP安全
>连接方式不同,HTTPS默认使用443端口,HTTP使用80端口


 

有没有使用过云主机(云服务)?


答:云服务器运行商提供的远程服务


有没有做过数据库优化?


1、查找定位慢查询:explain
2、建立索引:创建合适的索引,加速查询
3、分表: 当一张表的数据比较多或者某些字段的值特别占空间,采用水平拆分或者垂直拆分
4、读写分离:服务器性能不能满足时,采用读写分离方式进行集群
5、使用缓存:redis

查找定位慢查询:

在项目自验项目转测试之前,在启动MySQL数据库是开启慢查询,并且把执行慢的语句写到日志中,在运行一定时间后,通过查看日志找到慢查询语句。
 使用explain +sql
慢查询语句,来详细分析语句的问题。

优化技巧:


允许冗余字段、选择合适的存储引擎、索引(占用磁盘、dml操作影响性能、不做查询没意义,字段
内容变化不频繁)组合索引(最左匹配,如果不以前面的字段、必须包含第一个字段为查询条件,索引失效)
对于like索引字段,如果是aaa%,索引有效,否则无效
如果条件中有or,每个字段都必须有索引,否则索引无效
如果列类型是字符串,在条件中必须用单引号引用起来,否则索引失效
如果mysql估计使用全部扫描比使用索引快,则不适用索引

sql查询优化器认为全表扫描效率比索引扫描高,就会使用全表扫描。

那么sql优化器是如何计算扫描效率的呢?

分表:水平分表(按行)和垂直分表(按列)


因为单个物理数据库的资源跟连接数是有限制的,所以在数据量或者并发量较大的情况下,需要将一个数据库拆分成多个数据库。 mysql数据库纪录达到百万级时,查询性能会变慢,容易造成表锁,甚至堆积很多链接,直接挂掉,水平分表会很大程度减少这些压力。<—— 水平分表(按行)

如果一张表中某个字段的值非常多(长文本、二进制等),而且只有很少的情况下会查询,这时候应该将其单独存储,用外键关联起来!<—— 垂直分表(按列)

考试详情:一般只关注分数,不关注详情

分库分表会带来什么问题?

分布式事务、跨库join、count、全局排序  (需要将多库、表的数据提取进行聚合处理)

水平分表策略:


1、按时间分(也是一种范围分)
  有一定的局限性,当数据有较强的时效性,很少有用户会查询几个月前的数据,可按月分表

2、按区间范围分
   一般在有严格自增id需求上,如按用户ID水平分表
   table1:user_id 从1 - 100w
   table2 :  user_id 从101 - 200w

3、hash分表(用的最多)
 通过一个原始目标的ID或者名称按一定的hash算法计算出数据存储的表名,然后访问相应的表。

分库分表的坑

1.分库分表的坑之扩容

分库、分表、垂直拆分和水平拆分

  • 分库: 因一个数据库支持的最高并发访问数是有限的,可以将一个数据库的数据拆分到多个库中,来增加最高并发访问数。

  • 分表: 因一张表的数据量太大,用索引来查询数据都搞不定了,所以可以将一张表的数据拆分到多张表,查询时,只用查拆分后的某一张表,SQL 语句的查询性能得到提升。

  • 分库分表优势:分库分表后,承受的并发增加了多倍;磁盘使用率大大降低;单表数据量减少,SQL 执行效率明显提升。

  • 水平拆分: 把一个表的数据拆分到多个数据库,每个数据库中的表结构不变。用多个库抗更高的并发。比如订单表每个月有500万条数据累计,每个月都可以进行水平拆分,将上个月的数据放到另外一个数据库。

  • 垂直拆分: 把一个有很多字段的表,拆分成多张表到同一个库或多个库上面。高频访问字段放到一张表,低频访问的字段放到另外一张表。利用数据库缓存来缓存高频访问的行数据。比如将一张很多字段的订单表拆分成几张表分别存不同的字段(可以有冗余字段)。

  • 分库、分表的方式:

    • 根据租户来分库、分表。

    • 利用时间范围来分库、分表。

    • 利用 ID 取模来分库、分表。

坑:分库分表是一个运维层面需要做的事情,有时会采取凌晨宕机开始升级。可能熬夜到天亮,结果升级失败,则需要回滚,其实对技术团队都是一种煎熬。

怎么做成自动的来节省分库分表的时间?

  • 双写迁移方案:迁移时,新数据的增删改操作在新库和老库都做一遍。

  • 使用分库分表工具 Sharding-jdbc  来完成分库分表的累活。

  • 使用程序来对比两个库的数据是否一致,直到数据一致。

坑: 分库分表看似光鲜亮丽,但分库分表会引入什么新的问题呢?

垂直拆分带来的问题

  • 依然存在单表数据量过大的问题。

  • 部分表无法关联查询,只能通过接口聚合方式解决,提升了开发的复杂度。

  • 分布式事处理复杂。

水平拆分带来的问题

  • 跨库的关联查询性能差。

  • 数据多次扩容和维护量大。

  • 跨分片的事务一致性难以保证。

分布式事务的坑

怎么理解事务?

  • 事务可以简单理解为要么这件事情全部做完,要么这件事情一点都没做,跟没发生一样。

  • 在分布式的世界中,存在着各个服务之间相互调用,链路可能很长,如果有任何一方执行出错,则需要回滚涉及到的其他服务的相关操作。比如订单服务下单成功,然后调用营销中心发券接口发了一张代金券,但是微信支付扣款失败,则需要退回发的那张券,且需要将订单状态改为异常订单。

保证分布式中的事务正确执行

分布式事务的几种主要方式

  • XA 方案(两阶段提交方案)

  • TCC 方案(try、confirm、cancel)

  • SAGA 方案

  • 可靠消息最终一致性方案

  • 最大努力通知方案

XA 方案原理

XA 方案

  • 事务管理器负责协调多个数据库的事务,先问问各个数据库准备好了吗?如果准备好了,则在数据库执行操作,如果任一数据库没有准备,则回滚事务。

  • 适合单体应用,不适合微服务架构。因为每个服务只能访问自己的数据库,不允许交叉访问其他微服务的数据库。

TCC 方案

  • Try 阶段:对各个服务的资源做检测以及对资源进行锁定或者预留。

  • Confirm 阶段:各个服务中执行实际的操作。

  • Cancel 阶段:如果任何一个服务的业务方法执行出错,需要将之前操作成功的步骤进行回滚。

应用场景:

  • 跟支付、交易打交道,必须保证资金正确的场景。

  • 对于一致性要求高。

缺点:

  • 但因为要写很多补偿逻辑的代码,且不易维护,所以其他场景建议不要这么做。

Sega 方案

基本原理:

  • 业务流程中的每个步骤若有一个失败了,则补偿前面操作成功的步骤。

适用场景:

  • 业务流程长、业务流程多。

  • 参与者包含其他公司或遗留系统服务。

优势:

  • 第一个阶段提交本地事务、无锁、高性能。

  • 参与者可异步执行、高吞吐。

  • 补偿服务易于实现。

缺点:

  • 不保证事务的隔离性。

可靠消息一致性方案

可靠消息一致性方案

基本原理:

  • 利用消息中间件 RocketMQ 来实现消息事务。

  • 第一步:A 系统发送一个消息到 MQ,MQ将消息状态标记为 prepared(预备状态,半消息),该消息无法被订阅。

  • 第二步:MQ 响应 A 系统,告诉 A 系统已经接收到消息了。

  • 第三步:A 系统执行本地事务。

  • 第四步:若 A 系统执行本地事务成功,将 prepared 消息改为 commit(提交事务消息),B 系统就可以订阅到消息了。

  • 第五步:MQ 也会定时轮询所有 prepared的消息,回调 A 系统,让 A 系统告诉 MQ 本地事务处理得怎么样了,是继续等待还是回滚。

  • 第六步:A 系统检查本地事务的执行结果。

  • 第七步:若 A 系统执行本地事务失败,则 MQ 收到 Rollback 信号,丢弃消息。若执行本地事务成功,则 MQ 收到 Commit 信号。

  • B 系统收到消息后,开始执行本地事务,如果执行失败,则自动不断重试直到成功。或 B 系统采取回滚的方式,同时要通过其他方式通知 A 系统也进行回滚。

  • B 系统需要保证幂等性。

最大努力通知方案

基本原理:

  • 系统 A 本地事务执行完之后,发送消息到 MQ。

  • MQ 将消息持久化。

  • 系统 B 如果执行本地事务失败,则最大努力服务会定时尝试重新调用系统 B,尽自己最大的努力让系统 B 重试,重试多次后,还是不行就只能放弃了。转到开发人员去排查以及后续人工补偿。

几种方案如何选择

  • 跟支付、交易打交道,优先 TCC。

  • 大型系统,但要求不那么严格,考虑 消息事务或 SAGA 方案。

  • 单体应用,建议 XA 两阶段提交就可以了。

  • 最大努力通知方案建议都加上,毕竟不可能一出问题就交给开发排查,先重试几次看能不能成功。

分布式ID生成策略

redis自增;

雪花算法;

MySQL自增主键;

uuid;

读写分离


 当一台数据库访问达到瓶颈(一台数据库最大支持数有限),用户并发访问过多,一台服务器无法支撑,这时候可以集群处理,
最常用的是读写分离。
 主从同步:
数据库最终会将数据持久化到磁盘上,集群中的数据库数据是一致的。主库用来写,其他数据库从主上同步
 读写分离:
使用负载均衡来实现(主库用来写,从库支持读)

数据库优化之缓存:


 在持久层和数据库之间添加缓存层 用户的数据已经缓存,用户将直接从缓存中读取,不操作数据库,缓存是操作内存
级的,访问速度快。

作用:减少数据库服务器压力,提升访问速度

hibernate的二级缓存无法支持分布式
redis作为中央缓存,集中管理

语句优化技巧:


DDL优化:


1、禁用索引:提升导入数据性能  导入前去索引  导入数据  加回索引


DML优化:


变多次提交为一次

JDBC 如何高效插入几百万条数据?

1、变多次提交为一次
2、使用批量操作


redis:中央缓存


web集群时作为session
缓存队列等
保存对象方式:JSON字符串、字节

数据淘汰机制:从已设置过期时间的数据里挑选最近最少使用的数据。


产品:充分考虑扩展性

zookeeper集群原理

zookeeper是一个分布式协调框架 文件系统+监听通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper
会通知客户端。
四种类型节点(持久节点、临时节点、持久顺序节点、临时顺序节点)

持久节点: 存储到磁盘

临时节点: 声明绑定周期、连接断开,节点信息直接删除

 

三大角色:领导者 跟随者 观察者

watcher 事件通知(节点变化、新增、修改、删除)

主节点写  如果请求落到从,从节点会将请求转发给主,然后再同步到从节点

主节点会将写请求以严格的zxid,全局唯一且顺序

如何初始化时加载数据到redis中?


在controller层的对象implements InitializingBean
回调afterPropertiesSet 

Cookie和Session的区别

总结一下Object这个基类

  • 重写equals()方法,就必须重写hashCode()的方法

  • equals()方法默认是比较对象的地址,使用的是==等值运算符

  • hashCode()方法对底层是散列表的对象有提升性能的功能

  • 同一个对象(如果该对象没有被修改):那么重复调用hashCode()那么返回的int是相同的!

  • hashCode()方法默认是由对象的地址转换而来的

  • equals()方法还有5个默认的原则:

    • 自反性--->调用equals()返回的是true,无论这两个对象谁调用equals()都好,返回的都是true

    • 一致性--->只要对象没有被修改,那么多次调用还是返回对应的结果!

    • 传递性--->x.equals(y)y.equals(z)都返回true,那么可以得出:x.equals(z)返回true

    • 对称性--->x.equals(y)y.equals(x)结果应该是相等的。

    • 传入的参数为null,返回的是false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值