Java后端面试整理(3)

数据库系统原理

  1. 什么是事务的ACID?
    • 原子性:事务被视为不可分割的最小单元,一个事务的所有操作要么全部成功要么全部失败回滚。回滚可以用undo log实现;
    • 一致性:事务对数据库的任何修改都必须满足定义好的规则(约束,级联,触发器等);
    • 隔离性:指的是事物之间的执行互不干扰,一个事物所做的修改在提交前对其他事务是不可见的。
    • 持久性:一旦事务提交,其所做的修改会永远保存到数据库中,使用redo log保证持久性;
  2. 常见的并发异常以及对应的隔离级别有哪些?
    • 丢失更新,这是所有数据库系统都不允许的并发异常,对应的隔离级别为未提交读;
    • 脏读,并发事务读取了其他事务未提交的更新,对应的隔离级别为可提交读;
    • 不可重复读,一个事务两次读取之间被别的事务修改了,对应的隔离级别为可重复读;
    • 幻读,主要针对插入删除操作,一个事务两次对某个范围的读取操作因为并发事务对该范围数据的插入或者删除导致结果不同,对应隔离级别为可串行化;

范式

分布式事务

  1. 什么是2PC,3PC?分别存在什么问题?

    2PC与3PC都能保证分布式事务的强一致性。 2PC增加事务协调者,对事务进行全局管理。第一阶段,协调者发出prepare命令,所有参与者接受指令后本地执行事务,写本地的redo和undo日志,但不提交。若不能成功准备贼返回终止;第二阶段,协调者收到所有确认回复后,如果都是ok,则发出commit命令,否则abort。参与者接收到commit消息后,提交事务,释放所有资源。 2PC存在的问题:

    • 同步阻塞,事务执行过程中,所有参与节点都是阻塞型的;
    • 单点故障,协调者是单点的;
    • 脑裂

MySQL

索引

  1. MySQL常见的索引类型有哪些?
    • 普通索引:alter table add index,没有任何限制;
    • 唯一索引:add unique,索引列的值必须唯一,允许有空值;
    • 主键索引:一种特殊的唯一索引,不允许有空值;
    • 全文索引:针对较大的字段;
    • 组合索引,建立多个列的索引,遵循最左前缀原则,应将最常用的列做限制条件放在最左边;
  2. MySQL的索引结构? B+树索引数据只存在叶子节点,叶子节点添加顺序指针,支持范围查询;哈希索引查询效率非常高,不支持范围查询,哈希冲突需要全表扫描;
  3. 有哪些数据结构可以作为索引结构?为什么MySQL选择了B+树,而不是B树或者红黑树? B树,B+树,红黑树。B+树多路索引,每层节点很多,降低了树高,红黑树树高较高,B+树能利用磁盘预读特性,相邻节点(页的大小)预先被载入,减少IO次数。B树内部节点存储数据,能存储的指针数变少。另一个原因,B+树叶子节点带顺序访问指针,支持range query,也提高了扫表的效率。
  4. 解释以下最左匹配原则。 利用联合索引最左的字段来构建B+树索引,查询时,首先匹配最左的字段。
  5. 什么时候使用索引?
    • 经常出现在group by,order by和distinct关键字后面的字段;
    • 经常连接的表,在连接字段上建立索引;
    • 经常出现在where子句中的字段;
    • 经常用作查询选择的字段;
  6. 主键索引和唯一索引的差别?
    • 主键索引一定会创建一个唯一索引,有唯一索引的列不一定是主键;
    • 主键不允许空值,唯一索引列允许空值;
    • 一张表只能有一个主键,但可以有多个唯一索引;
    • 主键可以被其它表引用位外键,唯一索引不可以;
  7. 什么情况下索引会失效?查询不走索引?
  8. 如何优化查询性能?

引擎

  1. MySQL有哪些引擎? InnoDB、MyISAM、Memory、Archive等。
  2. InnoDB和MyISAM的区别有哪些?
    • 事务支持:InnoDB支持事务,MyISAM不支持。InnoDB默认情况下开启autocommit,每一条SQL都会封装成事务;
    • 外键:InnoDB支持外键,MyISAM不支持,对于一个包含外键的InnoDB表转为MyISAM会失败;
    • 索引:InnoDB支持聚簇索引,每个表必须有主键,未指定主键的表默认生成一个主键,使用B+树作为索引结构,数据文件和主键索引绑定,而MyISAM非聚簇索引,支持无主键的表,存的是每一行记录的地址;MySQL5.7之后,InnoDB与MyISAM均支持全文索引;
    • 表锁差别:InnoDB支持表级锁和行级锁,MyISAM只支持表级锁;
  3. InnoDB为什么推荐使用自增ID作为主键? 使用自增ID可以保证每次插入时,B+树索引是从右边扩展的,这样可以避免B+树的频繁分裂和合并。
  4. InnoDB的双写是怎么做的?为什么要双写?

扩展

分片

  1. 为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)

    一开始可能用单机数据库就够了,随着请求增多,使用主从架构进行读写分离,master处理写请求,slave处理读请求,slave从master同步更新数据。但用户量级上来以后,写请求越来越多,一个master处理不过来,资源不够,这时候就需要分库分表,对写请求进行切分。具体来说分库分表有如下原因:

    • 用户请求量太大,单服务器的内存,IO有限;
    • 单个数据库太大,单个数据库处理能力有限,磁盘空间不足,造成IO瓶颈;
    • 单表太大,CRUD成问题,索引膨胀,查询超时;
  2. 如何设计分库分表?

    垂直切分:

    • 垂直分表:大表拆小表,针对几百列的大表,把不常用的,数据较大的,长度较长(blob类型)的字段拆分到扩展表;
    • 垂直分库:把多个依赖不强的表分到不同库中; 水平切分:
    • 水平分表:按某种规则,比如range,hash取模等,把一张表的记录切分到多张表里面去,这些表还在同一个库中;
    • 水平分库分表:单张表数据水平切分到多个服务器上,规则可以是range、hash取模、地理区域、时间等;
  3. 有哪些分库分表中间件?client方案和proxy方案各有什么优缺点? sharding-jdbc:client方式。 mycat:proxy方式,通过定义表的分片规则来实现分片,每张表绑定一个分片规则,每个分片规则指定一个分片字段并绑定一个函数。 client方式优点在于不用部署,运维成本低,不需要代理二次转发,性能高,缺点是耦合高,依赖sharding-jdbc; proxy优点,解耦和的,应用透明使用,缺点在于需要部署,维护一套中间件。 无论什么模式,流程相似,SQL解析,重写,路由,执行,结果合并。

  4. 分库分表后会面临哪些问题?

    • 分布式事务,影响性能:2PC
    • 跨节点的join操作:1)全局表,每个节点存一份;2)字段冗余,反范式设计;3)数据组装,分两次查询;4)ER分片,根据ER图,有关联的放在一个分片
    • 跨界点order,limit,函数,各分片取出结果再做一次合并
    • 全局主键,uuid,中心化的sequencer,snowflake分布式自增ID
    • 数据迁移,扩容问题

复制

  1. 主从复制的原理(流程)?

    复制的前提,master数据库上开启了binlog。

    • master在事务提交之前,将操作记录写入binlog。
    • slave开启一个I/O thread,该线程在master打开一个连接,进行binlog dump流程,如果已经与master同步,则进入休眠状态等待master产生新的事件;该线程最终将操作记录写入中继日志中。
    • SQL线程读取中继日志,顺序执行该日志的SQL事件。img
  2. MySQL的四种传统复制方式?

    从数据同步方式的角度看,MySQL支持4中不同的同步方式:

    • 同步复制:master等待所有的slave复制完毕返回ack之后回复客户端,延迟太高,MySQL不采用;
    • 半同步复制:只需等待任意一个slave的回应,可设置超时,超时后自动降级位异步复制,网络延迟小可使用半同步复制;
    • 异步复制:即master执行完立即返回客户端,不管slave是否开始复制,问题在于slave复制过程中,master宕机,出现数据不一致;
    • 延迟复制:slave延迟一段时间再从master复制;
  3. MySQL的读写分离怎么做的? 在多个服务器上部署mysql,将其中一台认为主数据库,而其他为从数据库,实现主从同步。其中主数据库负责主动写的操作,而从数据库则只负责主动读的操作(slave从数据库仍然会被动的进行写操作,为了保持数据一致性),这样就可以很大程度上的避免数据丢失的问题,同时也可减少数据库的连接,减轻主数据库的负载。

Redis

  1. Redis 是什么?Redis 有哪些功能?都有哪些使用场景?

    Redis是一个高性能的kv内存数据库,也支持事务,持久化的NoSQL数据库,支持list,set,zset和hash数据结构的存储,NoSQL数据库没有固定的模式,加机器横向扩展很容易(主从,哨兵,集群)。Redis一般适用于高并发读写,海量数据的读写,也可作为消息队列,定时器或计数器使用,一下是几个Redis’常用的场景:

    • 最新的项目列表,如最新的评论ID;
    • 排行榜,取Top N操作
  2. Redis支持的对象数据类型,以及每种类型适用场景?

    Redis内部使用一个redisObject对象来表示所有类型的key和value,主要信息如下图:type表示一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式

    • String:简单的kv类型,value可以是字符串或者数字,常用命令有getsetincrdecr等,批量操作mgetmset,用作常规计数,微博数,粉丝数等;
    • List:列表数据类型(lpushrpushlpoprpoplrange),可以存储一些列表型的数据,例如粉丝列表,文章评论列表等,也可做消息队列,如限时抢购、秒杀等记录商品数量变化,lrange可做分页;
    • Hash:hgethsethgetall等,value存的field和value的映射表,适合存储对象,key+filed就可操作对应的属性数据,常用作存储用户信息,cookie信息等,编码方式为ziplist和ht(哈希表),使用拉链法解决哈希冲突;
    • Set:String类型的无序集合,不允许重复,通过hashtable实现去重,可做交集,并集,差集操作,系统部署在多台机器,可全局去重,共同好友,共同兴趣之类的;
    • Sorted Set:相比set多了一个权重参数,元素按照score排序,默认升序,可做排行榜应用,top n,内部使用hashtable和skiplist保证数据顺序;
  3. Redis有哪些架构模式?各有什么特点?

    • 单机版 特点简单,但是单机内存容量、处理能力有限,且单点故障,无法实现高可用;

    • 主从复制 master提供服务,slave提供同步和备份,降低maste读压力,没有解决master的写压力;

    • 哨兵

    • 单实例哨兵主从架构single_sentinel哨兵监控master和slave的存活状况,保证一台redis服务器宕机时,可以切换到另一台。引入新的单点,sentinel。

    • 双实例哨兵主从架构double_sentinel两个哨兵同时为客户端提供服务发现功能,主从切换需要一半以上sentinel进程可以联通,重新投票选取master,仍然存在异常使得无法提供服务;

    • 三实例哨兵主从架构 双实例架构的基础上单独部署一个哨兵实例; - 集群imgp2p网络,Gossip协议,无中心节点,每个节点都应该有从节点,采用哈希分区将数据划分到不同节点上,每个节点负责一部分的slot,数据均匀分配到16383个槽,投票容错机制判断节点是否挂了;

  4. Redis为什么使用单线程工作模型?为什么单线程这么快?

    使用单线程的原因,使用Redis时,CPU很少会称为瓶颈,要么是内存,要么是网络。单线程指的是在处理网络请求的时候只有一个线程,持久化的时候会有其他线程处理。

    • 纯内存操作
    • 单线程操作避免上下文切换
    • 采用非阻塞多路I/O复用机制 多路I/O复用模型是一个线程利用select、poll和epoll可以同时检查多个socket的I/O事件的能力,程序轮询一遍所有的socketfd(epoll只轮询发出事件的流),依次顺序处理。
  5. Redis的过期策略以及内存淘汰机制有哪些?

    Redis用作缓存,很多数据就是临时缓存一下,用过之后很久不用,比如session信息,redis如何清理不用的数据,过期的数据,redis支持对key设置过期时间。

    • 定时删除:设置key的过期时间,创建一个定时器,过期时间到,立即删除。存在问题,如果同时过期的key很多,cpu时间都用在删除过期key上,影响响应时间和吞吐;
    • 定期删除:redis每隔100ms随机抽取一批设置了过期时间的key,检查是否过期,但是会造成很多过期的key没有被删除;
    • 惰性删除:在获取某个key的时候检查是否过期; Redis采用定期删除+惰性删除结合的过期策略。如果定期删除漏掉了很多过期的key,然后也没有及时去查询这些key,内存会耗尽,这时候就会走内存淘汰机制,Redis支持以下的淘汰机制,在redis.conf中配置maxmemory-policy,默认为noeviction。
    • noeviction:当内存不足新写入数据时,报错;
    • volatile-lru:LRU移除设置过到期时间的key;
    • allkeys-lru:LRU移除任意key;
    • volatile-random:随机移除设置过到期时间的key;
    • allkeys-random:随机移除任意key;
    • volatile-ttl:有限移除设置过到期时间的过期时间最早的key;
  6. 什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

    持久化就是把内存的数据写到磁盘中去,防止服务器宕机内存数据丢失。 Redis提供两种持久化方式:

    • 默认的RDB,rdbSaverdbLoad,RDB通过快照方式完成,fork一个子进程开始将内存中的数据写入硬盘中的临时文件(二进制压缩存储),父进程继续处理来自客户端的请求。当子进程写完所有数据后,用改临时文件替换旧的rdb文件。值得注意的是,fork之后,父子进程共享一块内存数据,采用操作系统的写时复制策略,当父进程需要修改某个数据,先复制一份,在副本上进行修改,也就是rdb文件存储的是执行fork那一刻的内存数据。当符合以下情况,会将内存中的全量数据生成一个副本储存到磁盘:

    • redis.conf中配置save 900 1,表示900秒之后,如果至少有一个key发生变化则dump快照;

    • 用户执行SAVEBGSAVE命令,阻塞与异步的区别;

    • 执行FLUSHALL命令,如果配置了自动快照条件,则进行快照操作;

    • 配置主从复制时,redis在复制初始化时进行dump - AOF,即append-only file,一般打开AOF持久化来降低进程终止导致的数据丢失,AOF可以将每一条写命令追加到磁盘文件,其实并不是每次更改数据库都写入aof文件,先写到buffer中,每隔30s同步到磁盘。AOF文件以纯文本的形式记录redis执行的命令。AOF重写是重新生成一份文件,一条记录的操作只会保留最新的一次,也是fork一个进程。 RDB的优点有:1)容易恢复,相比aof启动效率高;2)子进程完成持久化工作,避免服务进程执行IO操作;缺点:1)数据丢失问题,定时持久化之前出现宕机,数据将丢失一部分;2)fork子进程时,虽然共享的数据内容无需复制,但是复制页表,数据很大的情况下,复制页表耗时。 AOF的优点有:1)更高的数据安全性;2)根据aof可完成数据的重建。缺点:1)aof文件通常更大,恢复速度慢;2)aof运行效率慢,特别是开启每修改同步。

  7. 使用缓存会有哪些问题?分别如何避免?

    • 缓存与数据库数据一致性问题,解决措施见12;
    • 缓存雪崩问题,即当缓存服务器重启或者大量缓存几种在某个时间失效,请求都到数据库上,可能会导致连接异常。避免的措施有:1)缓存失效后,通过加锁或者队列控制读数据库写缓存的线程数;2)设置二级缓存,I级失效时,可以访问II级,II失效时间长或者设置为不失效;3)缓存失效时间加一个随机值,避免集体失效。
    • 缓存穿透问题,一些恶意请求故意查询一个一定不存在的key,请求量很大,数据库压力很大。避免的措施有:1)不存在的key也缓存起来,设置一个较短失效时间;2)提供一个布隆过滤器过滤查询一定不存在key的请求;
  8. Redis的内存优化手段有哪些?

    https://www.cnblogs.com/jandison/p/6902396.html

    • 缩短key和value的长度,value可序列化为byte数组,json或者xml格式的value也可通过gzip压缩;
    • redis维护一个0-9999的整数对象池,但设置maxmemory和淘汰策略(LRU)后,禁止共享对象池, 因为LRU需要获取对象的最后访问时间。
  9. 如何使用Redis实现消息队列? 利用redis的list数据结构做队列,用lpushrpop或者rpushlpop,push和pop的对象为message序列化后的byte数组即可。消费者下线的情况下,生产的消息可能会丢失。

  10. 一致性哈希是什么?缺点?如何改进? 一致性哈希最早提出是为了解决分布式缓存的一致性问题,首先计算key的哈希,映射到0~2^32的圆上,从映射位置顺时针找,将数据保存到找到的第一个服务器上。 一致性哈希在服务节点较少时,容易因为节点分布不均匀而造成数据倾斜的问题。引入虚拟节点,即每个服务节点计算多个哈希,每个计算结果位置放一个虚拟节点,相对均匀。

  11. Redis如何配置LRU? 设置maxmemory,配置maxmemory-policy为volatile-lru或者allkeys-lru策略。

  12. 如何保证缓存与数据库双写一致性? Cache Aside Pattern:读数据先读缓存,缓存没有,再读数据库,取出数据后放入缓存,再返回客户端;写数据,先更新数据库,再删除缓存。

# resume 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×