java 高级面试题(借鉴)(中)

Spring Boot ⾃动配置原理?

        @Import + @Configuration + Spring spi
        ⾃动配置类由各个starter提供,使⽤@Configuration + @Bean定义配置类,放到METAINF/spring.factories下
        使⽤Spring spi扫描META-INF/spring.factories下的配置类
        使⽤@Import导⼊⾃动配置类

如何理解 Spring Boot 中的 Starter

        使⽤spring + springmvc使⽤,如果需要引⼊mybatis等框架,需要到xml中定义mybatis需要的beanstarter就是定义⼀个starter的jar包,写⼀个@Configuration配置类、将这些bean定义在⾥⾯,然后在starter包的META-INF/spring.factories中写⼊该配置类,springboot会按照约定来加载该配置类;
        开发⼈员只需要将相应的starter包依赖进应⽤,进⾏相应的属性配置(使⽤默认配置时,不需要配置),就可以直接进⾏代码开发,使⽤对应的功能了,⽐如mybatis-spring-boot--starter,springboot-starter-redis

Spring Boot是如何启动Tomcat的

        1. ⾸先,SpringBoot在启动时会先创建⼀个Spring容器
        2. 在创建Spring容器过程中,会利⽤@ConditionalOnClass技术来判断当前classpath中是否存在Tomcat依赖,如果存在则会⽣成⼀个启动Tomcat的Bean
        3. Spring容器创建完之后,就会获取启动Tomcat的Bean,并创建Tomcat对象,并绑定端⼝等,然后启动Tomcat

Spring Boot中配置⽂件的加载顺序是怎样的?

优先级从⾼到低,⾼优先级的配置覆盖低优先级的配置,所有配置会形成互补配置。
    1. 命令⾏参数。所有的配置都可以在命令⾏上进⾏指定;
    2. Java系统属性(System.getProperties());
    3. 操作系统环境变量 ;
    4. jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置⽂件
    5. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置⽂件 再来加载不带profile
    6. jar包外部的application.properties或application.yml(不带spring.profile)配置⽂件
    7. jar包内部的application.properties或application.yml(不带spring.profile)配置⽂件
    8. @Configuration注解类上的@PropertySource

bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml

Mybatis的优缺点

优点:
    1. 基于 SQL 语句编程,相当灵活,不会对应⽤程序或者数据库的现有设计造成任何影响,SQL 写在XML ⾥,解除 sql 与程序代码的耦合,便于统⼀管理;提供 XML 标签, ⽀持编写动态 SQL 语句, 并可重⽤。
    2. 与 JDBC 相⽐,减少了 50%以上的代码量,消除了 JDBC ⼤量冗余的代码,不需要⼿动开关连接;
    3. 很好的与各种数据库兼容( 因为 MyBatis 使⽤ JDBC 来连接数据库,所以只要JDBC ⽀持的数据库 MyBatis 都⽀持)。
    4. 能够与 Spring 很好的集成;
    5. 提供映射标签, ⽀持对象与数据库的 ORM 字段关系映射; 提供对象关系映射标签, ⽀持对象关系组件维护。
缺点:
    1. SQL 语句的编写⼯作量较⼤, 尤其当字段多、关联表多时, 对开发⼈员编写SQL 语句的功底有⼀定要求。
    2. SQL 语句依赖于数据库, 导致数据库移植性差, 不能随意更换数据库。
 

#{}和${}的区别是什么?

#{}是预编译处理、是占位符, ${}是字符串替换、是拼接符。
Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调⽤ PreparedStatement 来赋值;
Mybatis 在处理 ${}替换成变量的值,调⽤ Statement 来赋值;
#{} 的变量替换是在DBMS 中、变量替换后,#{} 对应的变量⾃动加上单引号,
${} 的变量替换是在DBMS 外、变量替换后,${} 对应的变量不会加上单引号
使⽤#{}可以有效的防⽌ SQL 注⼊, 提⾼系统安全性。

 简述 Mybatis 的插件运⾏原理,如何编写⼀个插件。

        Mybatis 只⽀持针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接⼝的插件, Mybatis 使⽤ JDK 的动态代理, 为需要拦截的接⼝⽣成代理对象以实现接⼝⽅法拦截功能, 每当执⾏这 4 种接⼝对象的⽅法时,就会进⼊拦截⽅法,具体就是 InvocationHandler 的invoke() ⽅法, 拦截那些你指定需要拦截的⽅法。

        编写插件: 实现 Mybatis 的 Interceptor 接⼝并复写 intercept()⽅法, 然后在给插件编写注解, 指定要拦截哪⼀个接⼝的哪些⽅法即可, 在配置⽂件中配置编写的插件。

索引的基本原理

索引⽤来快速地寻找那些具有特定值的记录。如果没有索引,⼀般来说执⾏查询时遍历整张表。
索引的原理:就是把⽆序的数据变成有序的查询

    1. 把创建了索引的列的内容进⾏排序
    2. 对排序结果⽣成倒排表
    3. 在倒排表内容上拼上数据地址链
    4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从⽽拿到具体数据
 

索引设计的原则?

查询更快、占⽤空间更⼩
    1. 适合索引的列是出现在where⼦句中的列,或者连接⼦句中指定的列
    2. 基数较⼩的表,索引效果较差,没有必要在此列建⽴索引
    3. 使⽤短索引,如果对⻓字符串列进⾏索引,应该指定⼀个前缀⻓度,这样能够节省⼤量索引空间,如果搜索词超过索引前缀⻓度,则使⽤索引排除不匹配的⾏,然后检查其余⾏是否可能匹配。
    4. 不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进⾏更新甚⾄重构,索引列越多,这个时间就会越⻓。所以只保持需要的索引有利于查询即可。
    5. 定义有外键的数据列⼀定要建⽴索引。
    6. 更新频繁字段不适合创建索引
    7. 若是不能有效区分数据的列不适合做索引列(如性别,男⼥未知,最多也就三种,区分度实在太低)
    8. 尽量的扩展索引,不要新建索引。⽐如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
    9. 对于那些查询中很少涉及的列,重复值⽐较多的列不要建⽴索引。
    10. 对于定义为text、image和bit的数据类型的列不要建⽴索引。

统计过慢查询吗?对慢查询都怎么优化过?

        慢查询的优化⾸先要搞明⽩慢的原因是什么?是查询条件没有命中索引?是load了不需要的数据列?还是数据量太⼤?
所以优化也是针对这三个⽅向来的
    ⾸先分析语句,看看是否load了额外的数据,可能是查询了多余的⾏并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进⾏分析以及重写。
    分析语句的执⾏计划,然后获得其使⽤索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。
    如果对语句的优化已经⽆法进⾏,可以考虑表中的数据量是否太⼤,如果是的话可以进⾏横向或者纵向的分表。

事务的基本特性和隔离级别

事务基本特性ACID分别是:

        原⼦性指的是⼀个事务中的操作要么全部成功,要么全部失败。

        ⼀致性指的是数据库总是从⼀个⼀致性的状态转换到另外⼀个⼀致性的状态。⽐如A转账给B100块钱,假设A只有90块,⽀付之前我们数据库⾥的数据都是符合约束的,但是如果事务执⾏成功了,我们的数据库数据就破坏约束了,因此事务不能成功,这⾥我们说事务提供了⼀致性的保证

        隔离性指的是⼀个事务的修改在最终提交前,对其他事务是不可⻅的。

        持久性指的是⼀旦事务提交,所做的修改就会永久保存到数据库中。

隔离性有4个隔离级别,分别是:

    read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。⽤户本来应该读取到id=1的⽤户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。
    read commit 读已提交,两次读取结果不⼀致,叫做不可重复读。不可重复读解决了脏读的问题,他只会读取已经提交的事务。⽤户开启事务读取id=1⽤户,查询到age=10,再次读取发现结果=20,在同⼀个事务⾥同⼀个查询读取到不同的结果叫做不可重复读。
    repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都⼀样,但是有可能产⽣幻读。
    serializable 串⾏,⼀般是不会使⽤的,他会给每⼀⾏读取的数据加锁,会导致⼤量超时和锁竞争的问题。
 

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

ACID靠什么保证的?

    A 原⼦性由undo log⽇志保证,它记录了需要回滚的⽇志信息,事务回滚时撤销已经执⾏成功的sql
    C ⼀致性由其他三⼤特性保证、程序代码要保证业务上的⼀致性
    I  隔离性由MVCC来保证
    D 持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,宕机的时候可以从redo log恢复

简述MyISAM和InnoDB的区别

MyISAM:
    1、不⽀持事务,但是每次查询都是原⼦的;
    2、⽀持表级锁,即每次操作是对整个表加锁;
    3、存储表的总⾏数;
    4、⼀个MYISAM表有三个⽂件:索引⽂件(.MYI )、表结构⽂件(.frm)、存储数据(.MYD)
    5、采⽤⾮聚集索引,索引⽂件的数据域存储指向数据⽂件的指针。辅索引与主索引基本⼀致,但是辅索引不⽤保证唯⼀性。

InnoDb: 
    1、⽀持ACID的事务,⽀持事务的四种隔离级别;
    2、⽀持⾏级锁及外键约束:因此可以⽀持写并发;
    3、不存储总⾏数;
    4、⼀个InnoDb引擎存储在⼀个⽂件空间(共享表空间,表⼤⼩不受操作系统控制,⼀个表可能分布在多个⽂件⾥),也有可能为多个(设置为独⽴表空,表⼤⼩受操作系统⽂件⼤⼩限制,⼀般为2G),受操作系统⽂件⼤⼩的限制;
    5、主键索引采⽤聚集索引(索引的数据域存储数据⽂件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使⽤⾃增主键,防⽌插⼊数据时,为维持B+树结构,⽂件的⼤调整。
    6、在磁盘上存储为2个文件:存储表的结构(.frm);存储表的数据和索引(.ibd)

简述Mysql中索引类型及对数据库的性能的影响

    普通索引:允许被索引的数据列包含重复的值。
    唯⼀索引:可以保证数据记录的唯⼀性。
    主键:是⼀种特殊的唯⼀索引,在⼀张表中只能定义⼀个主键索引,主键⽤于唯⼀标识⼀条记录,使⽤关键字 PRIMARY KEY 来创建。
    联合索引:索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引。
    全⽂索引:通过建⽴ 倒排索引 ,可以极⼤的提升检索效率,解决判断字段是否包含的问题,是⽬前搜索引擎使⽤的⼀种关键技术。可以通过ALTER TABLE table_name ADD FULLTEXT (column);创建全⽂索引

     1、索引可以极⼤的提⾼数据的查询速度。
     2、通过使⽤索引,可以在查询的过程中,使⽤优化隐藏器,提⾼系统的性能。
     3、但是会降低插⼊、删除、更新表的速度,因为在执⾏这些写操作时,还要操作索引⽂件
     4、索引需要占物理空间,除了数据表占数据空间之外,每⼀个索引还要占⼀定的物理空间,如果要建⽴聚簇索引,那么需要的空间就会更⼤,如果⾮聚集索引很多,⼀旦聚集索引改变,那么所有⾮聚集索引都会跟着变。

Explain语句结果中各个字段分表表示什么

 

索引覆盖是什么

        索引覆盖就是⼀个SQL在执⾏时,可以利⽤索引来快速查找,并且此SQL所要查询的字段在当前索引对应的字段中都包含了,那么就表示此SQL⾛完索引后不⽤回表了,所需要的字段都在当前索引的叶⼦节点上存在,可以直接作为结果返回了

最左前缀原则是什么

        当⼀个SQL想要利⽤索引是,就⼀定要提供该索引所对应的字段中最左边的字段,也就是排在最前⾯的字段,⽐如针对a,b,c三个字段建⽴了⼀个联合索引,那么在写⼀个sql时就⼀定要提供a字段的条件,这样才能⽤到联合索引,这是由于在建⽴a,b,c三个字段的联合索引时,底层的B+树是按照a,b,c三个字段从左往右去⽐较⼤⼩进⾏排序的,所以如果想要利⽤B+树进⾏快速查找也得符合这个规则

Innodb是如何实现事务的

Innodb通过Buffer Pool,LogBuffer,Redo Log,Undo Log来实现事务,以⼀个update语句为例:
    1. Innodb在收到⼀个update语句后,会先根据条件找到数据所在的⻚,并将该⻚缓存在Buffer Pool中
    2. 执⾏update语句,修改Buffer Pool中的数据,也就是内存中的数据
    3. 针对update语句⽣成⼀个RedoLog对象,并存⼊LogBuffer中
    4. 针对update语句⽣成undolog⽇志,⽤于事务回滚
    5. 如果事务提交,那么则把RedoLog对象进⾏持久化,后续还有其他机制将Buffer Pool中所修改的数据⻚持久化到磁盘中
    6. 如果事务回滚,则利⽤undolog⽇志进⾏回滚

Mysql锁有哪些,如何理解

按锁粒度分类:
    1. ⾏锁:锁某⾏数据,锁粒度最⼩,并发度⾼
    2. 表锁:锁整张表,锁粒度最⼤,并发度低
    3. 间隙锁:锁的是⼀个区间
还可以分为:
    1. 共享锁:也就是读锁,⼀个事务给某⾏数据加了读锁,其他事务也可以读,但是不能写
    2. 排它锁:也就是写锁,⼀个事务给某⾏数据加了写锁,其他事务不能读,也不能写
还可以分为:
    1. 乐观锁:并不会真正的去锁某⾏记录,⽽是通过⼀个版本号来实现的
    2. 悲观锁:上⾯所的⾏锁、表锁等都是悲观锁
在事务的隔离级别实现中,就需要利⽤锁来解决幻读

Mysql慢查询该如何优化?

1. 检查是否⾛了索引,如果没有则优化SQL利⽤索引
2. 检查所利⽤的索引,是否是最优索引
3. 检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据
4. 检查表中数据是否过多,是否应该进⾏分库分表了
5. 检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源

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。

Redis的过期键的删除策略

Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。

    惰性过期:只有当访问⼀个key时,才会判断该key是否已过期,过期则清除。该策略可以最⼤化地节省CPU资源,却对内存⾮常不友好。极端情况可能出现⼤量的过期key没有再次被访问,从⽽不会被清除,占⽤⼤量内存。
    定期过期:每隔⼀定的时间,会扫描⼀定数量的数据库的expires字典中⼀定数量的key,并清除其中已过期的key。该策略是⼀个折中⽅案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

Redis中同时使⽤了惰性过期和定期过期两种过期策略。

Redis线程模型、单线程快的原因

单线程快的原因:
    1)纯内存操作
    2)核⼼是基于⾮阻塞的IO多路复⽤机制
    3)单线程反⽽避免了多线程的频繁上下⽂切换带来的性能问题

Redis有哪些数据结构?分别有哪些典型的应⽤场景?

Redis的数据结构有:
    1. 字符串:可以⽤来做最简单的数据,可以缓存某个简单的字符串,也可以缓存某个json格式的字符串,Redis分布式锁的实现就利⽤了这种数据结构,还包括可以实现计数器、Session共享、分布式ID
    2. 哈希表:可以⽤来存储⼀些key-value对,更适合⽤来存储对象
    3. 列表:Redis的列表通过命令的组合,既可以当做栈,也可以当做队列来使⽤,可以⽤来缓存类似微信公众号、微博等消息流数据
    4. 集合:和列表类似,也可以存储多个元素,但是不能重复,集合可以进⾏交集、并集、差集操作,从⽽可以实现类似,我和某⼈共同关注的⼈、朋友圈点赞等功能
    5. 有序集合:集合是⽆序的,有序集合可以设置顺序,可以⽤来实现排⾏榜功能
 

Redis分布式锁底层是如何实现的?

    1. ⾸先利⽤setnx来保证:如果key不存在才能获取到锁,如果key存在,则获取不到锁
    2. 然后还要利⽤lua脚本来保证多个redis操作的原⼦性
    3. 同时还要考虑到锁过期,所以需要额外的⼀个看⻔狗定时任务来监听锁是否需要续约
    4. 同时还要考虑到redis节点挂掉后的情况,所以需要采⽤红锁的⽅式来同时向N/2+1个节点申请锁,都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到

Redis集群策略

Redis提供了三种集群策略:
    1. 主从模式:这种模式⽐较简单,主库可以读写,并且会和从库进⾏数据同步,这种模式下,客户端直接连主库或某个从库,但是但主库或从库宕机后,客户端需要⼿动修改IP,另外,这种模式也⽐较难进⾏扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能⽀持特⼤数据量
    2. 哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕机,然后在从库中选择⼀个库作为进的主库,另外哨兵也可以做集群,从⽽可以保证但某⼀个哨兵节点宕机后,还有其他哨兵节点可以继续⼯作,这种模式可以⽐较好的保证Redis集群的⾼可⽤,但是仍然不能很好的解决Redis的容量上限问题。
    3. Cluster模式:Cluster模式是⽤得⽐较多的模式,它⽀持多主多从,这种模式会按照key进⾏槽位的分配,可以使得不同的key分散到不同的主节点上,利⽤这种模式可以使得整个集群⽀持更⼤的数据容量,同时每个主节点可以拥有⾃⼰的多个从节点,如果该主节点宕机,会从它的从节点中选举⼀个新的主节点。


    对于这三种模式,如果Redis要存的数据量不⼤,可以选择哨兵模式,如果Redis要存的数据量⼤,并且需要持续的扩容,那么选择Cluster模式。
 

缓存穿透、缓存击穿、缓存雪崩分别是什么

缓存中存放的⼤多都是热点数据,⽬的就是防⽌请求可以直接从缓存中获取到数据,⽽不⽤访问Mysql。
    1. 缓存雪崩:如果缓存中某⼀时刻⼤批热点数据同时过期,那么就可能导致⼤量请求直接访问Mysql了,解决办法就是在过期时间上增加⼀点随机值,另外如果搭建⼀个⾼可⽤的Redis集群也是防⽌缓存雪崩的有效⼿段
    2. 缓存击穿:和缓存雪崩类似,缓存雪崩是⼤批热点数据失效,⽽缓存击穿是指某⼀个热点key突然失效,也导致了⼤量请求直接访问Mysql数据库,这就是缓存击穿,解决⽅案就是考虑这个热点key不设过期时间
    3. 缓存穿透:假如某⼀时刻访问redis的⼤量key都在redis中不存在(⽐如⿊客故意伪造⼀些乱七⼋糟的key),那么也会给数据造成压⼒,这就是缓存穿透,解决⽅案是使⽤布隆过滤器,它的作⽤就是如果它认为⼀个key不存在,那么这个key就肯定不存在,所以可以在缓存之前加⼀层布隆过滤器来拦截不存在的key
 

Redis和Mysql如何保证数据⼀致

    1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致
    2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中,这种⽅案能解决1⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到Redis中
    3. 延时双删,步骤是:先删除Redis缓存数据,再更新Mysql,延迟⼏百毫秒再删除Redis缓存数据,这样就算在更新Mysql时,有其他线程读了Mysql,把⽼数据读到了Redis中,那么也会被删除掉,从⽽把数据保持⼀致
 

Redis的持久化机制

RDB:Redis DataBase 将某⼀个时刻的内存快照(Snapshot),以⼆进制的⽅式写⼊磁盘

⼿动触发:
    save命令,使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,所以在⽣产环境⼀定要慎⽤
    bgsave命令,fork出⼀个⼦进程执⾏持久化,主进程只在fork过程中有短暂的阻塞,⼦进程创建之后,主进程就可以响应客户端请求了
⾃动触发:
    save m n :在 m 秒内,如果有 n 个键发⽣改变,则⾃动触发持久化,通过bgsave执⾏,如果设置多个、只要满⾜其⼀就会触发,配置⽂件有默认配置(可以注释掉)
    flushall:⽤于清空redis所有的数据库,flushdb清空当前redis所在库数据(默认是0号数据库),会清空RDB⽂件,同时也会⽣成dump.rdb、内容为空
    主从同步:全量同步时会⾃动触发bgsave命令,⽣成rdb发送给从节点

优点:
    1. 整个Redis数据库将只包含⼀个⽂件 dump.rdb,⽅便持久化。
    2. 容灾性好,⽅便备份。
    3. 性能最⼤化,fork ⼦进程来完成写操作,让主进程继续处理命令,所以是 IO 最⼤化。使⽤单独⼦进程来进⾏持久化,主进程不会进⾏任何 IO 操作,保证了 redis 的⾼性能
    4. 相对于数据集⼤时,⽐ AOF的启动效率更⾼。
缺点:
    1. 数据安全性低。RDB 是间隔⼀段时间进⾏持久化,如果持久化之间 redis 发⽣故障,会发⽣数据丢失。所以这种⽅式更适合数据要求不严谨的时候)
    2. 由于RDB是通过fork⼦进程来协助完成数据持久化⼯作的,因此,如果当数据集较⼤时,可能会导致整个服务器停⽌服务⼏百毫秒,甚⾄是1秒钟。会占⽤cpu


AOF:Append Only File 以⽇志的形式记录服务器所处理的每⼀个写、删除操作,查询操作不会记录,以⽂本的⽅式记录,可以打开⽂件看到详细的操作记录,调操作系统命令进程刷盘
1. 所有的写命令会追加到 AOF 缓冲中。
2. AOF 缓冲区根据对应的策略向硬盘进⾏同步操作。
3. 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。
4. 当 Redis 重启时,可以加载 AOF ⽂件进⾏数据恢复。同步策略:每秒同步:异步完成,效率⾮常⾼,⼀旦系统出现宕机现象,那么这⼀秒钟之内修改的数据将会丢 失每修改同步:同步持久化,每次发⽣的数据变化都会被⽴即记录到磁盘中,最多丢⼀条 不同步:由操作系统控制,可能丢失较多数据

优点:
    1. 数据安全
    2. 通过 append 模式写⽂件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redischeck-aof ⼯具解决数据⼀致性问题。
    3. AOF 机制的 rewrite 模式。定期对AOF⽂件进⾏重写,以达到压缩的⽬的
缺点:
    1. AOF ⽂件⽐ RDB ⽂件⼤,且恢复速度慢。
    2. 数据集⼤的时候,⽐ rdb 启动效率低。
    3. 运⾏效率没有RDB⾼
对⽐:
    AOF⽂件⽐RDB更新频率⾼,优先使⽤AOF还原数据。AOF⽐RDB更安全也更⼤
    RDB性能⽐AOF好
    如果两个都配了优先加载AOF
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值