聊聊面试那些事~
Redis的持久化有哪几种方式:
答:两种,分为rdb和apf。
rdb是Redis默认使用的持久化方式,之所以采用这种方式是因为此种速度快,并且对于数据不是特别严谨的情况下才能使用。
rdb有以下几种触发方式:
1.在redis的配置文件中,redis.conf,可以通过设置save来触发,例如:
save 60 5;这代表如果60秒内修改了5次key,就会触发。
2.执行清库命令,flushall命令,也会触发rdb。
3.退出Redis,也会产生rdb文件,备份就会自动生成一个dump.rdb文件,如上图所以dump.rdb。
可以通过如下的一个图来看一下这个rdb持久化的流程:
分析:
1.rdb在指定时间间隔内将内存中的数据集快照写入磁盘,恢复时是将这个快照文件直接读到内存里。Redis会单独创建一个fork子进程来就行持久化,会将数据写入到一个临时文件中,等持久化的这个过程结束了,再用这个临时文件替换上次持久化好的文件,整个过程中,主进程是不进行IO操作的,这就确保了极高的性能,主进程继续忙它自己的事,但是rdb有一个特点,上边已经提过:如果进行大规模数据恢复且对于数据恢复的完整性不是非常敏感的话,那rdb要比aof高效一些。
2. 但是缺点就是因为rdb持久化的方式中间是有时间间隔的,如果在这个时间段断电的话,宕机,那就不行了,所以它适合对数据不是特别严谨的场景,但是它的执行效率又比aof快,所以redis默认就是这种,一般情况下不需要修改此项配置。rdb保存的文件就是上边已经说到的dump.rdb,这个在redis的配置文件中进行操作,即redis.conf。
3. 有的时候,假如dump.rdb这个文件损坏了,我们还可以修复它,只需要将此文件放在redis的启动目录中即可,redis启动的时候会自动检查,自动修复。
再来介绍一下AOF:
aof比较容易理解,这个持久化的方式是把我们所有输入的命令都记录下来,类似于当在Linux中输入history命令时,会显示我们历史的命令。
恢复时就把这个文件全部执行一遍。
流程图:
分析:
以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来,读操作不记录,只许追加文件但不能改写文件,redis启动之初会读取该文件并重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
同样的类似rdb的dump.rdb,aof也有他自己的保存文件:appendonly.aof这个也是在redis的配置文件中修改:默认是未开启的,把no改为yes,然后再重启redis即可。
需要注意:当这个aof文件中如果有错误的话,redis是启动不起来的,需要手动修复这个aof配置文件(appendonly.aof),Redis提供了一个工具:redis-check-aof --fix
如图,连接redis:
如果文件正常,重启就可以直接恢复了。
可以再来查看下aof的一些参数:
aof的优点:
1.每一次修改都会同步,文件的完整性更好。
2.每秒同步一次,可能会丢失一秒的数据。
3.从不同步,效率是最高的。
缺点:
相对于数据来说,aof远远大于rdb,但修复的速度要比rdb慢。
说下线程池的原理或者是执行流程:
答:Java中提供了一个类Executor来帮助我们创建,但是不允许使用这种方式,因为这种方式对线程池的控制粒度比较低,不好控制。 其实这个看一下这个Executor创建的线程池:
所以推荐手动创建线程池,用ThreadPoolExecutor。
线程池的执行流程:
想一个问题:就是为啥要先进阻塞队列再去尝试创建非核心线程呢?
举个例子,饭店就好比一个线程池,在这个饭店里会有许多厨子,而这些厨子负责炒菜在执行任务,把厨子比作每一个个的线程,当客人满了的情况下,肯定是我们先让他排队吧,此时排队这个过程就好比一个阻塞队列,当然今天排队,明天排队,这也不是个事啊,该招厨子了就得招,那这个招厨子的过程中就是创建的最大核心线程数,最后,今天的座位客人都坐满了,那么好了,剩下的人,明天再来吧,先不接待了,这就是拒绝策略。
ThreadPoolExecutor有7个重要的参数:
1.核心线程数。
2.最大线程数。
3.空闲时间。
4.时间单位。
5.阻塞队列(工作队列)。
6.线程工厂。
7.拒绝策略(有4种)
4种拒绝策略: