目录
事务
2、Redis的乐观锁 Watch
Redis的持久化
1、RDB (Redis DataBase)
2、AOF(Append Only File)
Redis缓存穿透和雪崩
缓存击穿
是什么?
为什么?
怎么解决?(面试会考)
缓存穿透
是什么?
怎么解决?
缓存雪崩
是什么?
怎么解决?
·相关系列:
redis入门
数据库中事务
事务的本质:
一组命令的集合!
一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!
一次性,顺序性,排他性,执行一系列的命令!
1、Redis的事务机制
Redis的事务使用过程:
开启事务 -- multi
命令入队 -- ....
执行事务 -- exec
所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!
悲观锁: 很悲观,认为什么时候都会出问题,无论做什么都会加锁!但是影响效率!
乐观锁: 很乐观,认为什么时候都不会出问题,所以不会加锁!更新数据时去判断一下,在此期间是否有人 修改过这个数据!MySQL的version的使用:先获取version,更新数据时比较version,看version 是否被修改
Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘中,那么一旦服务器进程退出,服务 器中的数据库状态也会消失。所以Redis提供了持久化的功能。
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文 件直接读到内存中。
Redis会单独创建(fork)一个子进程来进程持久化,会先将数据写入到一个临时文件中,待持久化 过程都结束了,再用这个临时文件替换上一次持久化好的文件。整个过程中,主进程是不进行任何IO操 作的,这就确保了极高的性能。如果需要进程大规模数据的恢复,且对数据恢复的完整性不是非常敏 感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
将所有写操作的命令都记录下来,类似history,恢复时将所有的命令都执行一遍! AOF保存的文件是appendonly.aof 如果这个aof文件被恶意修改,这个时候redis是启动不起来的,我们需要修复这个aof文件! redis提供的一个工具 redis-check-aof --fix 来修改aof文件
面试:RDB\AOF区别?
AOF完整性好、修复速度慢于RDB
缓存穿透的就是用户想要查询一个数据,发现Redis中没有,也就是缓存没有命中,于是向持久层数 据库发起查询,发现也没有这个数据,于是本次查询失败。当用户很多的情况下,缓存都没有命中,又 都去请求持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于缓存穿透。
(量太大,缓存过期):本来时间就拥有大量的并发,被很多人访问。
解决方案1 -- 布隆过滤器 布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合 的则丢弃,从而避免对持久层数据库的查询压力。
解决方案2--缓存空对象 当存储层不命中后,及时返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个 数据将会从缓存中获取,保护了后端数据源。
(查不到)是用户想要查询一个数据,发现Redis中没有,也就是缓存没有命中,于是向持久层数 据库发起查询,发现也没有这个数据,于是本次查询失败。当用户很多的情况下,缓存都没有命中,又 都去请求持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于缓存穿透。
解决方法1 -- 热点数据永不过期 从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
解决方案2 -- 加互斥锁 分布式锁: 使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得 分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁 的考验比较大。
是在某一时间段,缓存集中过期失效,或者Redis宕机。比如:在写文本的时候,马上 要到双十一零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。 那么到了凌晨一点钟的时候,这批商品的缓存就过期了。从而对这批商品的访问查询,都落到了后台数 据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调 用量会暴增,造成存储层也会宕机的情况。
解决方案1 -- Redis高可用 这个思想就是说既然Redis有可能挂掉,我就多增设几台Redis,这样一台挂掉之后其他的还可以继续 工作,其实就是搭建缓存服务器集群。(异地多活)
解决方案2 -- 限流降级 这个思想就是在缓存失效后,通过加锁或者队列来控制读写数据库的线程数量。比如对某个key只允 许一个线程查询数据和写缓存,其他线程等待。
解决方案3 -- 数据预热 数据预热的含义就是在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数 据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间, 让缓存失效的时间点尽量均匀。