后端常见面试题

持续更新中……

1.为什么建议InnoDB表必须建主键,并且单分片架构下推荐使用整形的自增主键?(由于多分片架构会造成不同分片生成相同的id,所以不能使用自增主键,可以使用雪花算法)

为什么必须建主键?

  因为InnoDB表中的数据必须要有一棵B+树的索引树来组织数据文件,如果没有建立主键说明就没有任何索引来组织数据,那肯定是不行的, mysql底层会从表的第一列开始找,如果这一列的每个数据都是非空且唯一的,那么mysql就会把这一列数据放到B+树里作为索引组织这张表的所有数据,如果没有找到非空且数据唯一的列,那么mysql会默默地建立一个隐藏列,用RowId来组织这棵B+树。mysql的资源是非常宝贵的,干嘛要mysql来帮我们来建立主键呢,所以说InnoDB表必须要建立主键。

为什么使用整形?

  有些公司使用uuid的字符串作为主键,但是字符串的比较是逐位转换成asci码进行比较,比整形慢很多。而且公司使用的高速SSD硬盘一般是比较昂贵的,使用整形会比字符串更节省空间。

为什么要自增?

​ 如果不是自增的,在插入某一条数据时,很可能会插入到某个已经放满元素的节点,B+树为了维护索引的有序,会进行平衡和分链的操作,而这些操作都是效率比较低的,如果使用自增的主键,都是往B+树的后面加元素,分链的概率是非常低的

2.为什么mysql底层一般使用B+树作为索引,而不是使用哈希索引?

  主要原因是哈希索引不支持范围查询,如果要进行范围查询只能转变成全表扫描,效率非常低。而B+树索引本身是一种排好序的数据结构,进行范围查找效率很高。

3.为什么mysql的二级索引树(或联合索引)的叶子节点要存放主键,而不是使用聚簇索引?

优点:

  当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引。

缺点:

  1. 二级索引体积可能会变大,因为二级索引中存储了主键的信息。
  2. 二级索引的访问需要两次索引查找。第一次通过查找二级索引找二级索引中叶子节点存储的主键的值;第二次通过这个主键的值去聚簇索引中查找对应的行。

4.以下哪一条sql语句会走联合索引?

在这里插入图片描述

最左前缀法则:

  如果引用了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。所以第一条会走联合索引。

为什么第2条和第3条不走联合索引?

  联合索引是先根据组合字段的先后顺序排序的,如果第一个字段相同再根据第二个字段排序,以此类推,第一条sql语句恰好符合最左前缀法则,而第2条和第3条sql语句跳过了前面的某些字段,从整体上是无序的,这样就不会走索引,从而进行全表扫描,效率很低。
在这里插入图片描述

5.为什么B+树的数据要全部放在叶子结点(数据页)(或为什么叶子结点要存放冗余索引字段)?

​  因为B+树的每个结点默认分配16KB的存储大小,如果非叶子结点也存放数据的话,会导致非叶子结点可以存放的索引字段数量变少,树的分叉就会变少,从而导致索引树的层数变高,从而降低查询效率。

6.为什么Inoodb的B+树叶子结点要使用双向指针?

  如果要查询小于某个字段的数据,会根据B+树索引找到等于这个字段的数据,然后根据双向指针向左扫描;同理,查找大于某个字段的值会根据双向指针向右扫描,所以使用双向指针是为了方便范围查找。

7.联合索引中有a, b, c字段,select * from t1 where b > n;会走索引吗?

  mysql会根据sql语句进行判断,如果觉得走索引会快一些,那就会走索引,否则走全表扫描,如果n比较小的时候,走索引可能要进行比较多次的回表扫描,回表扫描次数多了效率较低,那mysql可能就会走全表扫描,如果n比较大,回表扫描次数小,mysql可能就会走索引。

8.解释一下缓存雪崩、缓存穿透、缓存击穿

  1.缓存雪崩
  1.1什么是缓存雪崩

  因缓存服务宕机或同一时间大量缓存过期,导致大量请求走数据库

  1.2解决办法
  1.2.1事前

  如果缓存雪崩造成的原因是因为缓存服务宕机造成的,可以将redis采用集群部署,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis 全盘崩溃的情况。
  若缓存雪崩是因为大量缓存因为失效时间而造成的,我们在批量往redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效。
  设置热点数据永远不过期,有更新操作就更新缓存就可以了。

  1.2.2事中

  限流和降级。让一部分请求允许访问数据库,其他服务走限流逻辑,然后调用我们自己开发的降级组件(比如延迟服务、页面跳转、设置默认值等)。

  1.2.3事后

  通过持久化的数据尽快恢复缓存

  2.缓存穿透
  2.1 什么是缓存穿透

  在正常的情况下,用户查询数据都是存在的,但是在异常情况下,缓存与数据库都没有数据,但是用户不断发起请求,这样每次请求都会打到数据库上面去,这时的用户很可能是攻击者,攻击会导致数据库压力过大,从而击垮数据库。

  2.2 解决办法
  2.2.1 添加参数校验

  作为一名后端开发工程师,不要相信前端传来的东西,所以数据一定要在后端进行校验。我们可以在接口层添加校验,不合法的参数直接返回即可,没必要做后续的操作。

  2.2.2 缓存空值

  这些key 设置的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null ,就不用在到 数据库中去走一圈了。但是别忘了设置过期时间。

  2.2.3 布隆过滤器

  redis的一个高级用法就是使用布隆过滤器(Bloom Filter),BloomFilter 类似于一个hash set 用来判断某个元素(key)是否存在于某个集合中。这个也能很好的防止缓存穿透的发生,他的原理也很简单就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。
  上面介绍了三种方法,用哪种方法最好呢?下面我们来分析一下:

  第一种方法,添加参数校验,这里是必须要添加,不过只能过滤掉一些特殊值,比如传的id为负数,如果传的正常id,这里参数校验就不起作用了。

  第二种方法,如果有一些恶意攻击,攻击会带来大量不存在的key,这样采用第二种方法就不合适了。所以针对这种key 异常多,请求重复率比较低的数据,我们就没有必要进行缓存,使用第三种方案直接过滤掉。
  如果对于空数据key有限的,重复率比较高的,我们则可以采用第二种方式进行缓存。

  3. 缓存击穿
  3.1 什么是缓存击穿

  我们在平常高并发的系统中,大量的请求同时查询一个key时,假设此时,这个key正好失效了,就会导致大量的请求都打到数据库上面去,这种现象我们称为击穿。

  这么看缓存击穿和缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是「缓存击穿」是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。

  缓存击穿带来的问题就是会造成某一时刻数据库请求量过大,压力剧增。

  3.2 解决办法
  3.2.1 不过期

  我们简单粗暴点,直接让热点数据永远不过期,定时任务定期去刷新数据就可以了。不过这样设置需要区分场景,比如某宝首页可以这么做。

  3.2.2 互斥锁

  为了避免出现缓存击穿的情况,我们可以在第一个请求去查询数据库的时候对他加一个互斥锁,其余的查询请求都会被阻塞住,直到锁被释放,后面的线程进来发现已经有缓存了,就直接走缓存,从而保护数据库。但是也是由于它会阻塞其他的线程,此时系统吞吐量会下降。需要结合实际的业务去考虑是否要这么做。

9.解释一下Redis大key和大value的危害

  大key和大value都会造成的问题有三点:

  1.内存不均:单value较大时,可能会导致节点之间的内存使用不均匀,间接地影响key的部分和负载不均匀;
  2.阻塞请求:redis为单线程,单value较大读写需要较长的处理时间,会阻塞后续的请求处理;
  3.阻塞网络:单value较大时会占用服务器网卡较多带宽,可能会影响该服务器上的其他Redis实例或者应用。
  key由于比value需要做更多的操作如hashcode、链表中比较等操作,所以大key会比大value更多一些内存相关开销。

  单个简单key的存储的value过大的解决方案:

  将大value拆分成多个key-value,使用multiGet方法获得值,这样的拆分主要是为了减少单台操作的压力,而是将压力平摊到集群各个实例中,降低单台机器的IO操作。

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值