一.什么是Redis?
redis是一款非关系型数据(key-value),主要作用是用来作为数据缓存,数据可以存储在内存中.
二.为什么要用Redis?
mysql中的数据直接存储在硬盘上的,每次查询连接mysql从硬盘上查询,
所以将一些更新较少(例如新闻类型、商品类型),短时间内查询较多的(秒杀,抢购)
从内存中查询数据,减轻了mysql的压力
三.Redis在项目中的作用?
缓存
计数器 incr key 值加1 decr key 值减1 点赞
排行榜 zset 排序
数据排重 set 不能存储重复元素
消息队列 list rput lpop
分布式锁 微服务中用到分布式
四.Redis线程模型
redis6.0之前是严格意义上的单线程,执行命令和处理客户端连接都是由一个线程完成的.
redis6.0之后引入了多线程,把处理客户端连接的任务交给一部分线程完成,
执行命令仍然由一个单线程完成,这样保证并发安全(访问量再大,都是一个一个的执行)
五.为什么是单线程执行命令,为什么还这么快
操作都是在内存中
底层基于哈希结构,查询/操作时,可以通过key计算出哈希值,快速的定位到位置
单线程模式,避免执行命令时,线程的切换.
六.Redis持久化
redis数据默认存储在内存中,一旦断电数据就没有了
所以redis提供了数据持久化功能
有两种持久化方式:
rdb方式:Redis DataBase 以快照方式,将redis中的数据写入到一个dump.rdb文件中
当满足条件时,自动执行, 也是redis中默认开启的持久化方法
自动持久化条件
save 900 1 900秒 有一次key的变化
save 300 10
save 60 10000
也可以直接执行save命令,主动的持久化
AOF方式:以日志的方式,记录redis中执行的写操作命令(set del),当下次还原是,执行日志文件,逐行执行命令,还原数据.
redis中默认没有开启aof持久化方式,如果需要开启,在redis配置文件中修改
以通过 appendfilename 参数修改
AOF同步机制
appendfsync always
#每次修改都会 sync。消耗性能
appendfsync everysec #每秒执行一次 sync,可能会丢失这1s的数据(默认)
重启 redis 生效
定时任务 例如点赞数量 redis-->mysql
七.Redis事物
redis中的事务,是将我们要执行的多条命令进行打包,当执行事务中的多条命令时作为一个整体,期间是不能插入其他命令,保证命令执行的原子性,但是执行时,又不保证命令执行成功的原子性,例如三条指令,两条成功,一条失败,即使有执行失败,不会让这三条命令回滚.
multi 开始事务
set a aa
set b bb
incr a
exec 执行事务
redisTemplate.multi(); 开启事务
ValueOperations valueOperations = redisTemplate.opsForValue();字符类型
valueOperations.set(k,v);
valueOperations.set();
valueOperations.set();
valueOperations.set();`
redisTemplate.exec();执行事务
八.Key过期策略
redis中的key可以进行定时存储
valueOperations.set(k,v, 5, TimeUnit.MINUTES);
key的过期策略,说的是,key的到期时间到达后,redis以何种机制删除到期的key
惰性删除:在key过期时间到达后,不会立即删除,只是将key的状态改为不可用,当下次使用时,才会删除过期的key
定期删除:在key过期时间到达后,将key的状态改为不可用,定时定期的主动删除过期的key
key会绑定一个回调函数,到期后,自动将状态给为不可以
九.缓存穿透、缓存击穿、缓存雪崩
1.缓存穿透(重点)
当查询一个数据库中没有的数据时(例如id=-1),redis没有,我们就去数据查询,此时缓存没有,被穿透了
如果别人恶意攻击,也会穿过redis,直接到达mysql,可能导致mysql崩溃
解决方案:
1.当mysql查询没有时,可以向redis也存放key-value value可以为aaa(标记),当从redis中取出值为aaa,表名mysql不存在,不再查询了
2.对参数的合法性进行验证,例如id没有-1的
3.使用布隆过滤器,进行验证
2.缓存击穿
数据库中数据存在,redis中的某个热点key突然过期,此时有大量请求同时到来,发现redis中没有,大量的请求查询mysql,导致mysql崩溃
解决方案:
1.热点数据设置较长过期时间
2.查询mysql时加锁,还可以在锁内二次判断是否已经查询到了,如果查询到了就不在查询mysql了
3.缓存雪崩
大量的key过期