本文基本都是阅读《Javaguide面试突击版》的总结,仅用于个人学习总结,如有侵权立刻删除。
原文链接:Javaguide面试突击版
1.Redis(remote dictinory sever)远程字典服务
- 是一个key-value数据库,提供多种语言的API
- 是当下最热门的结构化数据库
能干嘛?
- 内存存储、持久化,内存中是断电即失,所以说持久化很重要(rdb、aof)
- 效率高,用于告诉缓存
- 发布订阅系统
- 计时器、浏览量
- 地图信息分析
特性:
- 多样的数据类型
- 持久化
- 集群
- 事务
2.简单介绍一下Redis
- 简单来说Redis就是一个使用C语言开发的数据库
- Redis的数据是存在内存中的
- Redis除了做缓存之外,Redis也经常用来做分布式锁,甚至是消息队列
- 提供多种数据类型来支持不同业务
3.分布式缓存的技术选型方案有哪些?
- 分布式缓存使用的较多的是Memcached和Redis,不过现在基本上都使用Redis
- 分布式缓存主要是为了解决单机缓存容量受服务器限制以及无法保存通用的信息,因为本地缓存只在当前服务有效,当你部署两个相同的业务时,两个相同的数据无法共通。
4.说一下Memcached和Redis的区别和共同点?
共同点:
- 都是基于内存的数据库,都被用来当作缓存使用
- 都有过期策略
- 两者性能都非常高
区别:
-
Redis支持更丰富的数据类型,Redis不仅支持键值对,还支持list、hash、set、zset数据类型,支持更丰富的应用场景。
-
Redis支持数据的持久化,可以把内存中的数据存在磁盘中,重启后可以重新加载使用,memcache把数据都存在内存中
-
Redis有灾难恢复机制,因为可以把数据存放在磁盘中
-
Redis内存使用完后,可以把数据存放在磁盘中,而Memcache会直接报异常。
-
Memcache没有原生的集群模式,而Redis是原生支持集群的
-
Memcache是多线程的非阻塞IO网络模型,Redis以前是单线程的多路IO复用模型,但在Redis6.0后也支持多线程了。
-
Redis支持发布订阅模型、事务,而Memcache不支持
-
Memcache过期策略只用了惰性删除,而Redis是用惰性删除与定期删除。
5.缓存数据的处理流程是什么?
- 用户请求数据
- 在缓存中查看有无该数据,有则直接返回。
- 无则到数据库中查看,有则更新到缓存中,然后返回该数据。
- 无则返回空数据。
6.为什么要使用Redis/为什么要使用缓存?
- 高性能:使用缓存是为了让用户有更好的体验,当用户第一次访问数据时,相对而言是比较慢的,因为是直接从硬盘中获取,如果当用户经常访问一个数据并且该数据不经常改变的话,我们可以把它放入缓存中,当下一次用户访问数据的时候,直接从缓存中读取,这比从硬盘获取要快得多。
- 高并发:使用缓存可以提高系统整体的并发,因为操作缓存所能承受的数据库请求数量是远远大于数据库的。
7.Redis之前没有使用多线程,为什么不使用多线程?
-
单线程编程更容易,且更容易维护
-
使用多线程可能会带来死锁、上下文切换等问题,甚至影响性能
-
Redis的性能瓶颈不在CPU,而在于内存和网络。
8.Redis之后为何又引入了多线程?
- 引入多线程主要是为了提高IO网络读写能力
- 引入多线程后Redis也只是在网络数据读写上使用了多线程,执行命令任然是按单线程顺序执行的。因此也不用担心线程安全问题
9.Redis缓存设置过期时间用什么作用?
- 因为内存时有限的,如果不给缓存数据设置过期时间,长时间残留的话会造程内存溢出。
- 而且有些情况我们往往就是希望数据在一定期限内有效,比如短信验证码只在1分钟内有效,如果用传统数据库的话还得自己判断过期,更麻烦且性能低
10.Redis是如何判断数据过期的呢?
- Redis通过过期字典来判断,过期字典的键指向数据库中的键,字典中的值保存着所指向着数据库键的过期时间。
11.过期的数据的删除策略了解过吗?(重要)
- 惰性删除: **只有当key被取出的时候才进行检查,将过期的删除,这样可能会造成一大批过期的key没被检查到没被删除,**但是这对CPU挺友好的。
- 定期删除:**Redis定期抽取一批key检查它们是否过期,过期了的就删除,并且Redis会通过限制删除执行的时长和频率来降低对CPU的影响。**这对内存挺友好。
12.内存淘汰机制
- volatile-least recently used:从已设置过期时间中删除最近最少使用的key
- volatile-time to live:从已设置过期时间中删除即将过期的key
- volatile-random :从已设过期时间中随机删除key
- allkeys-least recently used:当内存不足时,从所有keys里删除最近最少使用的key
- allkeys -random:当内存不足时,从所有keys里随机删除keys
- no-eviction:禁止驱逐,当内存不够时,新写入数据会报错
redis4.0后又引入了两种新的内存淘汰机制:
- volatile-least frequently used:在已设置过期时间中的keys中删除不经常使用的keys
- allkeys-least frequently used:当内存不足时,在所有keys当中删除不经常使用的keys
13.Redis持久化机制(怎么保证Redis挂掉后再重启数据可以进行恢复)
-
快照持久化(RDB):
Redis可以通过快照来获取在内存中某个数据在某个时间点的副本,并可以将他备份在服务器或者保存在本地,以便下次重启时使用。
-
AOF持久化(append only file)只追加文件:
Redis每执行一次命令就把该命令写入硬盘中的AOF文件中,实时性更好。
14. Redis事务
Redis不支持回滚,不满足原子性(也不满足持久性)
官网开发者解释这样更简单便捷,认为没有必要支持回滚,开发者觉得即使执行命令发生错误应当在开发过程中被发现,而不是生产过程中
15.缓存穿透
-
什么是缓存穿透?
当用户的请求都没有经过缓存而是全部直接访问数据库的时候就是缓存穿透,比如说假设有个黑客为了攻击,恶意制造了大量不存在缓存中的key,让这些大量的请求直接落到数据库上
-
如何解决?
- 参数校验,对请求的一些参数提前做校验,不对就直接返回异常给用户(比如邮箱格式、查询数据id不能等于0之类的)
- 缓存无效key,假如我们知道一些不会存在于缓存和数据库中的key,我们把它提前存在缓存中,并给他设置过期时间。
- 布隆过滤器:将可能存在的请求提前放在布隆过滤器中,如果用户提交的请求没有存在布隆过滤器中,直接返回错误给用户。
16.缓存雪崩
-
什么时缓存雪崩?
当有大量请求积攒在缓存中时,缓存突然失效导致大面积的请求全部落在数据库上,比如一个秒杀系统,提前设置了一批商品订单在缓存中,当秒杀开始的时候缓存失效了,就会造成缓存雪崩
-
如何解决?
- 采用redis集群,避免单机崩溃而导致整个服务失效。
- 限流,避免处理大量请求
- 随机设置缓存失效时间或是直接缓存永不失效