java常问面试题10道,offer来碗里(三)

目录

1.redis持久化机制

2.Redis和Mysql如何保证数据⼀致性的?

3.TCP的三次握⼿和四次挥⼿

4.mysql数据库的事务

5.索引实效的情景有哪些?

6.如何保证多线程,每个线程顺序执行?

7.Java死锁如何避免?

什么是死锁?

8.Mysql索引的底层数据结构,B树和B+树的区别,为什么Mysql使⽤B+树?

9.HTTPS是如何保证安全传输的?

10.谈一下你未来几年的职业规划?


1.redis持久化机制

RDB 和 AOF

RDB:Redis DataBase 在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写 入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

优点:

1、整个Redis数据库将只包含一个文件 dump.rdb,方便持久化。

2、容灾性好,方便备份。

3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进 程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能

4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:

1、数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢 失。所以这种方式更适合数据要求不严谨的时候)

2、由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导 致整个服务器停止服务几百毫秒,甚至是1秒钟。

AOF:Append Only File 以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以 打开文件看到详细的操作记录

优点:

1、数据安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也 是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据 将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁 盘中。。

2、通过 append 模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redischeck-aof 工具解决数据一致性问题。

3、AOF 机制的 rewrite 模式。定期对AOF文件进行重写,以达到压缩的目的

缺点:

1、AOF 文件比 RDB 文件大,且恢复速度慢。

2、数据集大的时候,比 rdb 启动效率低。

3、运行效率没有RDB高 AOF文件比RDB更新频率高,优先使用AOF还原数据。 AOF比RDB更安全也更大 RDB性能比AOF好 如果两个都配了优先加载AOF

2.Redis和Mysql如何保证数据⼀致性的?

1.延时双删,步骤是:先删除Redis缓存数据,再更新Mysql,延迟⼏百毫秒再删除Redis缓存数据, 这样就算在更新Mysql时,有其他线程读了Mysql,把⽼数据读到了Redis中,那么也会被删除掉, 从⽽把数据保持⼀致(非常常用的)

2. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致

3. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中,这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中

3.TCP的三次握⼿和四次挥⼿

TCP协议是7层⽹络协议中的传输层协议,负责数据的可靠传输。

在建⽴TCP连接时,需要通过三次握⼿来建⽴,过程是:

1. 客户端向服务端发送⼀个SYN

2. 服务端接收到SYN后,给客户端发送⼀个SYN_ACK

3. 客户端接收到SYN_ACK后,再给服务端发送⼀个ACK

在断开TCP连接时,需要通过四次挥⼿来断开,过程是:

1. 客户端向服务端发送FIN

2. 服务端接收FIN后,向客户端发送ACK,表示我接收到了断开连接的请求,客户端你可以不发数据 了,不过服务端这边可能还有数据正在处理

3. 服务端处理完所有数据后,向客户端发送FIN,表示服务端现在可以断开连接

4. 客户端收到服务端的FIN,向服务端发送ACK,表示客户端也会断开连接了

4.mysql数据库的事务

什么是数据库事务?

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行(要么都成功,要么都要失败)。


事物的四大特性(ACID)介绍一下?

关系性数据库需要遵循ACID规则,具体内容如下:

事务的特性

    1.  原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
    2.一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
    3.隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
    4.持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

什么是脏读?幻读?不可重复读?

    脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
    不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
    幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

什么是事务的隔离级别?MySQL的默认隔离级别是什么?

为了达到事务的四大特性,数据库定义了4种不同的事务隔离级别,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

 SQL 标准定义了四个隔离级别:

    READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
    READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
    REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
    SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

这里需要注意的是:Mysql 默认采用的 REPEATABLE_READ(可重复读)隔离级别 Oracle 默认采用的 READ_COMMITTED(读取已提交)隔离级别

5.索引实效的情景有哪些?

索引失效的10种场景,你知道几个呢?(必知五颗星)

6.如何保证多线程,每个线程顺序执行?

1.使用join

     thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

t.join();      //调用join方法,等待线程t执行完毕
t.join(1000);  //等待 t 线程,等待时间是1000毫秒。

2.使用CountDownLatch

     CountDownLatch(闭锁)是一个很有用的工具类,利用它我们可以拦截一个或多个线程使其在某个条件成熟后再执行。它的内部提供了一个计数器,在构造闭锁时必须指定计数器的初始值,且计数器的初始值必须大于0。另外它还提供了一个countDown方法来操作计数器的值,每调用一次countDown方法计数器都会减1,直到计数器的值减为0时就代表条件已成熟,所有因调用await方法而阻塞的线程都会被唤醒。这就是CountDownLatch的内部机制,看起来很简单,无非就是阻塞一部分线程让其在达到某个条件之后再执行。

3.CachedThreadPool

     FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消。

     一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执行(excution).

4.使用blockingQueue

     阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。并发包下很多高级同步类的实现都是基于BlockingQueue实现的。

5.使用单个线程池

     newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。

public class ThreadTest5 {
 
public static void main(String[] args) throws InterruptedException {
    final Thread t1 = new Thread(new Runnable() {
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run 1");
        }
    }, "T1");
    final Thread t2 = new Thread(new Runnable() {
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run 2");
            try {
                t1.join(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "T2");
    final Thread t3 = new Thread(new Runnable() {
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run 3");
            try {
                t2.join(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }, "T3");
 
    //使用 单个任务的线程池来实现。保证线程的依次执行
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(t1);
    executor.submit(t2);
    executor.submit(t3);
    executor.shutdown();
 }
}

详细可参考:https://blog.csdn.net/Evankaka/article/details/80800081 

7.Java死锁如何避免?

什么是死锁

所谓死锁:是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进

产生死锁的必要条件:

    互斥条件:⼀个资源每次只能被⼀个线程使⽤
    请求和保持条件:⼀个线程在阻塞等待某个资源时,不释放已占有资源
    不剥夺条件:⼀个线程已经获得的资源,在未使⽤完之前,不能被强⾏剥夺
    环路等待条件:若⼲线程形成头尾相接的循环等待资源关系

这是造成死锁必须要达到的4个条件,如果要避免死锁,只需要不满⾜其中某⼀个条件即可。⽽其中前3个 条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件,不出现循环等待锁的关系。

在开发过程中:

1. 要注意加锁顺序,保证每个线程按同样的顺序进⾏加锁

2. 要注意加锁时限,可以针对所设置⼀个超时时间

3. 要注意死锁检查,这是⼀种预防机制,确保在第⼀时间发现死锁并进⾏解决

8.Mysql索引的底层数据结构,B树和B+树的区别,为什么Mysql使⽤B+树?

B树的特点:

1. 节点排序

2. ⼀个节点了可以存多个元素,多个元素也排序了

B+树的特点:

1. 拥有B树的特点

2. 叶⼦节点之间有指针

3. ⾮叶⼦节点上的元素在叶⼦节点上都冗余了,也就是叶⼦节点中存储了所有的元素,并且排好顺序

Mysql索引使⽤的是B+树:因为索引是⽤来加快查询的,⽽B+树通过对数据进⾏排序所以是可以提⾼查询 速度的,然后通过⼀个节点中可以存储多个元素,从⽽可以使得B+树的⾼度不会太⾼,在Mysql中⼀个 Innodb⻚就是⼀个B+树节点,⼀个Innodb⻚默认16kb,所以⼀般情况下⼀颗两层的B+树可以存2000万 ⾏左右的数据,然后通过利⽤B+树叶⼦节点存储了所有数据并且进⾏了排序,并且叶⼦节点之间有指针, 可以很好的⽀持全表扫描,范围查找等SQL语句。

9.HTTPS是如何保证安全传输的?

https通过使⽤对称加密、⾮对称加密、数字证书等⽅式来保证数据的安全传输。

1. 客户端向服务端发送数据之前,需要先建⽴TCP连接,所以需要先建⽴TCP连接,建⽴完TCP连接后, 服务端会先给客户端发送公钥,客户端拿到公钥后就可以⽤来加密数据了,服务端到时候接收到数据就 可以⽤私钥解密数据,这种就是通过⾮对称加密来传输数据

2. 不过⾮对称加密⽐对称加密要慢,所以不能直接使⽤⾮对称加密来传输请求数据,所以可以通过⾮对称 加密的⽅式来传输对称加密的秘钥,之后就可以使⽤对称加密来传输请求数据了

3. 但是仅仅通过⾮对称加密+对称加密还不⾜以能保证数据传输的绝对安全,因为服务端向客户端发送公 钥时,可能会被截取

4. 所以为了安全的传输公钥,需要⽤到数字证书,数字证书是具有公信⼒、⼤家都认可的,服务端向客户 端发送公钥时,可以把公钥和服务端相关信息通过Hash算法⽣成消息摘要,再通过数字证书提供的私 钥对消息摘要进⾏加密⽣成数字签名,在把没进⾏Hash算法之前的信息和数字签名⼀起形成数字证 书,最后把数字证书发送给客户端,客户端收到数字证书后,就会通过数字证书提供的公钥来解密数字 证书,从⽽得到⾮对称加密要⽤到的公钥。

5. 在这个过程中,就算有中间⼈拦截到服务端发出来的数字证书,虽然它可以解密得到⾮对称加密要使⽤ 的公钥,但是中间⼈是办法伪造数字证书发给客户端的,因为客户端上内嵌的数字证书是全球具有公信 ⼒的,某个⽹站如果要⽀持https,都是需要申请数字证书的私钥的,中间⼈如果要⽣成能被客户端解 析的数字证书,也是要申请私钥的,所以是⽐较安全了。

10.谈一下你未来几年的职业规划?

技术面试官的话,个人觉得要要强调对技术的追求,想在技术提高的渴望,不怕加班,不怕吃苦。

HR的话,稳定性,稳定性,稳定性。比如想找一个靠谱的公司待个三四年,但时候结合自己的情况,冲刺大厂,或是走技术+管理路线。

之前总结的,常问干货:

java常问面试题10道,offer来碗里(一)

java常问面试题10道,offer来碗里(二)

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

only-qi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值