(必看)java面试重难点之数据库专题-Redis
未完待续,持续更新,如果有用,记得点赞收藏关注。
1、redis为什么这么快
(一)纯内存操作(二)单线程操作,避免了多线程频繁上下文切换带来的损耗。
(三)采用了非阻塞I/O多路复用机制
2、什么是上下文?
上下文是指某一时间点 CPU 寄存器和程序计数器的内容。
寄存器是 CPU 内部的数量较少但是速度很快的内存(与之对应的是 CPU 外部相对较慢的 RAM 主内存)。
寄存器通过对常用值(通常是运算的中间值)的快速访问来提高计算机程序运行的速度。 程序计数器是一个专用的寄存器,用于表明指令序列中 CPU 正在执行的位置,存的值为正在执行的指令的位置或者下一个将要被执行的指令的位置,具体依赖于特定的系统。
上下文切换(有时也称做进程切换或任务切换)是指 CPU 从一个进程或线程切换到另一个进程或线程。
上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行以下的活动:(1)挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处,(2)在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复,(3)跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。
上下文切换有时被描述为内核挂起 CPU 当前执行的进程,然后继续执行之前挂起的众多进程中的某一个。尽管这么说对于澄清概念有所帮助,但是这句话本身可能有一点令人困惑。因为通过定义可以知道,进程是指一个程序运行的实例。所以说成挂起一个进程的运行可能更适合一些。
3、为什么要⽤ redis
2、高并发:可以同时接受很多请求,比数据库能承受的请求量多得多。
4、redis和memcached的区别
5、缓存雪崩
缓存雪崩与缓存击穿的区别在于这里针对很多key缓存,前者则是某一个key
解决方案:
(1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
(2)如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
(3)设置热点数据永远不过期。
6、缓存击穿
(1)设置热点数据不过期。
(2)加互斥锁。(涉及到分布式锁的一个排坑功能)
7、缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 (1) 对空值缓存:如果一个查询返回的数据为空(不管是数据是否不存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟
(2) 设置可访问的名单(白名单):
使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。
(3) 采用布隆过滤器:
将所有可能存在的数据哈希到一个足够大的bitmaps中,一个一定不存在的数据会被 这个bitmaps拦截掉,从而避免了对底层存储系统的查询压力。
(4) 进行实时监控:当发现Redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务
8、布隆过滤器是什么
将要添加的元素跟k个hash函数计算求得k个hash值,并把每个hash值指向的bit数组位置的值置为1
布隆过滤器查询元素:
将要查询的元素与k个hash函数进行计算求个k个hash值,判断这k个hash值指向的bit数组位置总值是否都为1,如果不全为1,证明该元素一定不存在。如果全为1,证明这个元素可能存在。
因为当多个元素与hash函数进行计算后,指向的bit数组位置很可能重复置为1,进行覆盖,无法判断是哪个元素让其数组值为1的。
这是为什么呢?答案跟简单,因为随着增加的值越来越多,被置为 1 的 bit 位也会越来越多,这样某个值 “taobao” 即使没有被存储过,但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 ,那么程序还是会判断 “taobao” 这个值存在。
9、redis的删除方式
定期删除:redis每隔100ms随机抽取一些设置了过期时间的key,检查是否过期,过期了则删除。这种方式是随机的,因此会有过期的key遗留下来,剩下的进行惰性删除。
惰性删除:对于遗留下来的过期key,只有系统进行查询才会被删除,不查询则不删除。
10、Redis内存淘汰机制
第一类:从已经设置过期时间的数据集中筛选(最近最少用,最不常用,任意数据,将要过期)第二种:在所有数据集中筛选(最近最少用,最不常用,任意数据)
11、Redis持久化方式有哪些
13、RDB与AOF的对比
13、AOF和RDB同时开启,redis听谁的?
14、如何保证缓存与数据库双写时的数据⼀致性?
1、延时双删
1、A线程先删除缓存再删除数据库,是为了让其他线程不是从缓存中拿到的是旧数据,但这种也会导致其他线程在删除数据前,从数据中读取到了数据又更新到缓存中
2、A线程删除缓存后再删除数据库再删除缓存,有可能导致B线程在更新数据库读取到了数据库的数据更新到缓存,给C线程读取了
3、所以采用延时双删,在B线程读取数据库更新缓存后再删除缓存,此时C线程读取到的缓存为空,就会从数据库中获取
分以下几种情况考虑在三中,第二次清空缓存之前,多延时一会儿,等B更新缓存结束了,再删除缓存,这样就缓存就不存在了,其他事务查询到的为新缓存。
延时是确保 修改数据库 -> 清空缓存前,其他事务的更改缓存操作已经执行完。