Redis数据类型
String (字符串)
Hash (哈希,key=>value键值对)
List (简单的字符串列表,按照插入顺序排列)
Set (String类型无序集合)
zset (sorted set: 有序集合)
缓存穿透、击穿、雪崩
读取数据时先去缓存(redis)中找,如果缓存中没有,就会去数据库中查。
缓存穿透:很多用户查询在缓存中没有命中,就去持久层数据库查。
用户想查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求持久层数据库。这会给持久层数据库造成很大压力,相当于出现了缓存穿透。
缓存穿透解决方案:
1.布隆过滤器,布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层进行检验,不符合也丢弃,从而避免了对底层存储系统的查询压力;
2.缓存空对象,当持久层不命中后,即使返回空对象也将其缓存起来,同时会设置一个过期时间,以后再访问这个数据将会从缓存中取,直到缓存过期,保护了后端数据原。
缓存击穿: 指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
缓存击穿解决方案:
1.设置热点数据永不过期;
2.加互斥锁,分布式锁:使用分布式锁,保证对于每一个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩:在某一时间段,缓存集中过期失效,redis宕机。
缓存雪崩解决方案:
1.redis高可用,搭建rsdis集群,异地多活;
2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库与写缓存的线程数量。比如对某一个key只允许一个线程查询数据和写缓存,其他线程等待;
3.数据预热,在正式部署之前,预先访问一遍数据,把大部分数据加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效时间点尽量均匀。
1、事务
Redis事务的本质: 一组命令的集合,一个事务的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!
所以,Redis单条命令是保证原子性的,但事务不保证原子性。
Redis的事务:
开启事务(multi)
命令入队(…)
执行事务(exec)
事务执行完后结束,再次执行需要重新开启事务。
取消/放弃事务(discard)
事务当时后,队列中的命令都不会被执行。
编译错误(相当于java中语法错误),事务中所有的命令都不会被执行!
运行时异常(如:1/0),其他命令正常执行,错误命令抛出异常。
2、Redis在java中的应用
3、Redis持久化
RDB:数据集快照,dump.rdb文件
优点:只有一个dump.rdb文件,方便持久化;容灾性好,一个文件可以保存到安全的磁盘;性能最大化,子进程完成持久化写操作,主进程继续处理命令;数据较大时,比AOF效率高。
缺点:数据安全性低,RDB是间隔一段时间持久化,若在此期间redis发生故障,会让数据丢失。
AOF:所有命令持久化,保存aof文件
优点:数据安全,每执行一次命令就记录到AOF文件中;
缺点:AOF文件比RDB文件大,恢复速度慢
持久化方式选择:两种同时使用,用AOF保证数据不丢失,作为数据恢复的第一选择;用RDB做备用,在AOF文件丢失或损坏时,使用RDB快速恢复数据。
如果同时使用RDB和AOF两种持久化机制,那么在Redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完善。
4、为什么redis单线程模型效率也能那么高:
1、 C语言实现,效率高
2、 纯内存操作
3、 基于非阻塞的IO复用模型机制
4、 单线程能避免多线程的频繁上下文切换问题
5、 丰富的数据结构(全程采用hash结构,读取速度非常快,对数据存储进行了一些优化)