笔记

142 阅读5分钟

一些不熟悉的面经

MVCC

  1. MVCC就是多版本并发控制,用于多个事务并发下读操作的非阻塞,以及RR级别下解决快照读的幻读问题。
  2. 主要是利用两个隐藏字段(当前事务id和undolog的回滚指针),undolog,版本链和readview快照视图。
  3. readview在产生的时候会记录当前所有的活跃的(也就是还没提交的)事务数组,所有事务中最大的事务id,活跃事务数组中最小的事务id。
  4. 通过一组比对规则从版本链中找到可见的最新的版本。minid和maxid将事务分成了三组:1. 小于minid的属于肯定已经提交的事务(可见)2. 在minid和maxid之间的包括提交和未提交的事务,如果在活跃事务数组中,则属于未提交(不可见),如果不在其中则(可见)3. 大于maxid的为还没有开始的事务id,肯定是(不可见)的。
  5. 在rr级别下,readview默认是在第一次select产生,并且一直保持,所以可以解决不可重复读和幻读的问题。在rc级别下,readview会再每一次select的时候产生。

快照读和当前读,怎么解决幻读问题;什么是间隙锁。

  1. 快照读就是读取快照readview中的数据,不需要加锁,通过mvcc实现,通过对比规则在版本链中找到可见的最新的版本数据返回。当前读就是读最新版本的消息,要加间隙锁和行锁组成nextkey锁。
  2. innodb默认是rr级别,快照读通过mvcc解决,当前读通过间隙锁解决。
  3. 由于加行锁无法锁住插入语句,所以进入间隙锁,n个行锁配合n+1个间隙锁组成nextkey锁,防止插入。

聚簇索引和非聚簇索引有什么区别,分别适用哪些场景

  1. 根本区别是表中记录的数据物理顺序和索引的排列顺序是否一致,聚簇索引是一致的,非聚簇索引是不一致的。
  2. 聚簇索引非叶子结点存储索引,叶子结点存储索引和整个行记录。而非聚簇索引是数据结构和索引结构分开存放的索引,叶子结点仍然是索引,通过索引再去访问数据。
  3. 聚簇索引优点就是查询速度快,定位到了索引就定位到了数据,并且叶子结点本身是有序的,能够很快速的查到范围或者排序的数据,缺点是为了保障顺序的一致性,插入或者修改数据时要对数据进行重排,重排的代价比较大。适用于小数目的不同值,且不适用于频繁更新插入的场景。
  4. 非聚簇索引插入数据时不会引起数据重排,适用于频繁更新和大数目的不同值。

redis相关

  1. 数据结构:string(计数) hash(对象) set(唯一无序交并差集) zset(权值排序排行榜,跳表) list(链表),bitmap(存储连续的二进制数字,表示状态,节省空间)
  2. 持久化:RDB快照(存储当前的所有数据副本为快照,可以用于重启加载,也可以复制给其他服务器作为容灾备份,或者主从结构提高性能,设置配置文件多少秒内有有多少key发生变化就会触发)和AOF只追加文件(记录所有对数据有变化的指令到内存缓存中,然后根据配置决定何时存储到AOF文件中,有每一次执行,每一秒和根据操作系统来决定,AOF重写解决体积膨胀,主要就是相同的数据库状态下,重写的aof文件不包含浪费空间的冗余命令,通过子进程和重写aof缓冲区实现)
  3. 缓存问题:缓存雪崩(大量的key同时失效)[分散的过期时间,永久key],缓存穿透(大量不存在的key,黑客攻击)[缓存无效key设置较短的时间,布隆过滤器],缓存击穿(热点数据过期)[设置为永久,在数据库方面加互斥锁,第一个到数据库的请求加锁获取后同步到redis中,后续的请求继续访问缓存)
  4. 架构:单机(内存有限,无法高可用),主从复制(主服务器复制多份为从服务器,主服务器负责写和同步数据到从服务器,从服务器负载均衡读压力,高可用的基石,master出了故障挑选slaver顶替,在此基础上搭建哨兵和集群,目前没有解决写压力和高可用),哨兵(监控提醒故障转移,解决的高可用),集群(将key按照一定规则分到指定的redis实例上,所有节点彼此互联通过二进制协议提高速度)
  5. 为什么快:内存数据库(硬盘需要通过磁头来寻址,机械转动比较慢,内存是通过电信号,瞬时到达)单线程的多路io复用模型,数据结构都是redis自己实现并且做了优化)
  6. 过期和内存淘汰:惰性(用到再淘汰)和定期(定期取一部分key检查),从allKeys或者过期字典中根据lru,lfu,random组合来选择淘汰的,或者不淘汰。
  7. 缓存和数据库一致性: