- 面试总结
- 问题汇总与答案整理(仅供参考)
- 1. 数据库中的事务是什么
- 2. 并发环境下,事务会带来哪些问题([并发事务引起的脏读、丢失修改、不可重复读、幻读等问题 ](https://www.cnblogs.com/kyoner/p/11305204.html))
- 3. 事务的隔离级别
- 4. MySQL的存储引擎
- 5. MySQL的索引
- 6. MySQL的最左匹配原则
- 7. Redis和MySQL有啥区别,Redis是单线程的为什么还这么快
- 8. Redis的数据类型有哪些
- 9. Redis跳表
- 10. Redis的热key问题如何解决
- 11. Redis的持久化机制
- 12. Redis的集群和哨兵机制
- 13. 缓存穿透和缓存雪崩
- 14. Redis的一致性哈希算法
- 15. Redis的分布式锁
- 16. MySQL的常用语法
数据库在Java工程师的面试过程中也是常问的一项,这里主要对2020年本人秋招时面试关于数据库原理,MySQL,Redis相关问题进行了总结
问题汇总与答案整理(仅供参考) 1. 数据库中的事务是什么事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。是满足ACID特性的一组操作。
A:Automic,原子性,事务的所有操作要么全部提交成功,要么全部失败回滚。
C:Consistency,一致性,事务应确保数据库的状态从一个一致状态转变成另一个一致状态。
I:Isolation,隔离性,多个事务并发执行时,一个事务的执行不会影响其他事务的执行。
D:Durability,持久性,已被提交的事务对数据库的修改应该永久保存在数据库中。
2. 并发环境下,事务会带来哪些问题(并发事务引起的脏读、丢失修改、不可重复读、幻读等问题 )丢失修改:指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失
读脏数据:指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。
不可重复读:指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
幻影读:幻影读是不可重复读的一种特殊场景。指的是事务1在查询的时候查出来5条数据,这时候事务2新插入了5条数据并且提交,事务1再次查询发现了10条数据,前后查询结果不一致就会导致幻影读。
3. 事务的隔离级别Read Uncommitted(读取未提交):能够读取到没有被提交的数据
Read Committed(读取已提交):能够读取已经提交的数据
Repeatable Read(可重复读):读取一条数据的时候如果这个事务不结束,那么别的事务也不可以修改这条数据
Serializable(串行化):最高的事务隔离级别,不管多少事务,只有一个事务执行完才能运行下一个
MySQL的的默认隔离级别是:可重复读
4. MySQL的存储引擎MySQL支持的引擎在5.5版本前默认为MyISAM,之后默认为InnoDB
区别在于:
-
InnoDB支持的行级锁,而MyISAM支持的是表级锁
-
InnoDB支持事务,而MyISAM不支持事务
-
InnoDB支持外键,而MyISAM不支持外键(外键用于与另一张表关联,是另一张表的主键)
-
InnoDB支持MVCC(多版本并发控制机制),MyISAM不支持
最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入MVCC之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。MVCC比单纯的加锁更高效,MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作,MVCC可以使用乐观锁和悲观锁来实现。其具体实现方式是保存数据在某个时间点的快照实现的,不同存储引擎的实现方法是不同的
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里的时间指的是系统版本号。比如InnoDB查询每行数据,必须确保如下两个标准
1.数据行的版本必须小于等于当前事务的版本 2.行的删除操作的版本一定是未定义的或者大于当前事务的版本号 -
InnoDB使用的是聚簇索引,而MyISAM使用的是非聚簇索引
聚簇索引指的是数据就存储在叶子节点上,而非聚簇索引叶子节点存储的不是数据本身,而是数据存放的地址
MySQL的索引按数据结构主要划分为B+树索引,哈希索引,FullText索引,R-Tree索引。
| 索引 | MyISAM引擎 | InnoDB引擎 | Memory引擎 |
|---|---|---|---|
| B+树索引 | 支持 | 支持 | 支持 |
| HASH索引 | 不支持 | 不支持 | 支持 |
| R-Tree索引 | 支持 | 不支持 | 不支持 |
| FullText索引 | 支持 | 暂不支持(现在支持) | 不支持 |
此外,按照物理存储角度还划分为聚簇索引和非聚簇索引。
6. MySQL的最左匹配原则在MySQL建立联合索引的时候会用到最左匹配原则,即最左优先,在查询的时候会从联合索引的最左边开始匹配。
7. Redis和MySQL有啥区别,Redis是单线程的为什么还这么快MySQL是关系型数据库,Redis是非关系型数据库。
mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢,redis用于存储使用较为频繁的数据到缓存中,读取速度快。
Redis快的原因(最新的Redis是支持多线程的了):
- 其是基于内存访问的,绝大部分请求都是纯粹的内存操作。
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作。
- 使用多路I/O复用模型。
Redis的数据类型主要包括:
| 数据类型 | 可以存储的值 |
|---|---|
| String | 字符串、整数或者浮点数 |
| List | 列表 |
| Set | 无序集合 |
| Hash | 包含键值对的无序散列表 |
| Zset | 有序集合 |
跳表是有序集合的底层实现,是基于多指针有序链表实现的,是以空间来换时间的方式来提高查找速度。 其数据结构如下:
跳表相较于红黑树等平衡树相比,具有以下优点:
- 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性
- 更容易实现且支持无锁操作
跳表的详细插入与查询可以见此博客[Redis跳表]((54条消息) 面试准备 – Redis 跳跃表_LuckyToMeet-Dian叶-CSDN博客_redis 跳表)
10. Redis的热key问题如何解决Redis的热key问题指的是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存服务的情情况。
要解决热key问题,首先要学会发现热key,发现热key有以下三种方法:
- 凭借业务经验,提前预估哪些是热key
- 在客户端进行收集
- 在Proxy层进行收集
- 用Redis自带命令进行统计分析
- 使用抓包工具进行评估
如何解决热key:
(1) 利用二级缓存
利用ehcache,或者一个HashMap都可以。在你发现热key以后,把热key加载到系统的JVM中。针对这种热key请求,会直接从jvm中取,而不会走到redis层。
(2) 备份热key
这个方法的目的是不要让key走到同一台redis上不就行了。我们把这个key,在多个redis上都存一份不就好了。接下来,有热key请求进来的时候,我们就在有备份的redis上随机选取一台,进行访问取值,返回数据
Redis的持久化机制主要有以下两种:
- RDB快照持久化:通过创建快照来获得存储在内存⾥⾯的数据在某个时间点上的副本
- AOF日志持久化:Redis会将每一个收到的写命令都通过write函数追加到文件中
Redis加载RDB文件的速度比AOF快很多,因为RDB文件中直接存储的时内存数据,而AOF文件中存储的是一条条命令,需要重演命令。但其缺点在于无法做到实时持久化,若在两次bgsave间宕机,则会丢失区间(分钟级)的增量数据,不适用于实时性要求较高的场景。AOF日志持久化是目前Redis的主流持久化方式,但是由于只是追加写日志文件,因此速度比RDB要快,但是其日志文件较大,因此其恢复数据速度较RDB文件慢。
12. Redis的集群和哨兵机制所谓的Redis集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态。
为什么需要Redis集群?
(1)单个redis存在不稳定性。当redis服务宕机了,就没有可用的服务了。
(2)单个redis的读写能力是有限的。
总的来说,Redis集群是为了强化读写能力。在redis集群中,每一个redis称之为一个节点,有两种类型的节点:主节点(master)、从节点(slave),整个redis集群是基于redis主从复制实现的。
Redis的主从复制:
Redis节点群中一个为主节点Master,从节点Slave可以有多个。
只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。主节点Master可读、可写,从节点Slave只读。因此,主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。
Redis的哨兵机制:
Redis的主从模式存在一个缺点,就是当主节点宕机了,整个集群就没有可写的节点了。因此哨兵机制的主要作用就是解决此问题。其主要任务如下:
监控(Monitoring): 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时,可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时,其会开始一次自动故障迁移操作, 它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
13. 缓存穿透和缓存雪崩缓存穿透:用户大量并发请求的数据(key)对应的数据在redis和数据库中都不存在,导致尽管数据不存在但还是每次都会查询数据库。
解决方法:
- 从DB中查询出来数据为空,也进行空数据的缓存,避免数据库数据为空也每次都进行数据库查询
- 使用布隆过滤器,但是会增加一定的复杂度及存在一定的误判率
缓存雪崩:大量key同一时间点失效,同时又有大量请求打进来,导致请求直接打在数据库上,造成数据库不可用。
解决方法:
- 设置key永不失效(热点数据)
- 设置key缓存失效时候尽可能错开
- 使用多级缓存机制,比如同时使用redsi和memcache缓存,请求->redis->memcache->db
由于Redis在工作情况下需要使用集群来提高性能,当数据量较大的时候,单独的一个Redis节点无法存储这么大,因此需要将数据存储在多个节点上。但假设在存储的过程中是随机存储的,这样在查询的时候就会面临每次都遍历的问题,查询时间慢。
因此如果在存储的时候如果采用Hash的方法,就可以根据哈希值对服务器数量取模存储到特定的Redis节点上,这样查询速度也会很快。但这样也会出现一个新的问题,即在Redis服务器数量变动的时候,所有缓存的位置都要发生改变!
Redis的一致性哈希算法就是为了解决此问题的。一致性Hash算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性Hash算法是对232取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,值空间为0-232-1。各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将四台服务器使用IP地址哈希后在环空间的位置如下。在存储数据时,定位数据访问的相应服务器:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。这样,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器。
更多关于一致性哈希算法的详情推荐大家看博客Redis一致性哈希算法
15. Redis的分布式锁这个问题可以参考如下博客分布式锁之Redis实现。
16. MySQL的常用语法有的公司是会考察这个的,会出一些相应的题目,但基本都是力扣上数据库的题的一些变式甚至是原题, 建议把力扣数据库的题刷一遍,非会员能做的就二十来个,面试官问的也基本在这里面



