redis知识点总结

一、Redis的五种常用数据结构

1、String

缓存热点数据。用于计数器(incr)。收藏、评论数量

2、list(列表)
字符串列表,按照插入顺序排序,可以在列表的头部和尾部添加元素。底层实现是一个双向链表,支持反向查找和遍历,但带来了额外的内存开销。删除效率高。

应用场景:如微博的关注列表、粉丝列表。

3、set(无序集合)
string类型的无序集合,不允许重复的元素,底层实现是哈希表,添加、删除、查找的时间复杂度均为O(1)。
set与list类似,都可以存储多个字符串,而set通过哈希表来保证存储的string是各不相同的。
应用场景:存储不能重复的元素,如:用户名不能重复。

4、zset(有序集合)
与set类似,也是string类型的集合,有序的且不允许重复的元素。
底层实现:内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score(优先级)的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
应用场景:范围查找、排行榜等。

5、hash(哈希)
key对应的值是一个hashmap,每个hash中存储field及对应的value,其关系如下图所示:

hash的优点就是根据key+field直接操作其中一个value,而不用重复存储全部数据。
应用场景:存储部分变更的数据,如:用户数据等。

三、Redis缓存穿透、缓存击穿、缓存雪崩
1、缓存穿透
key对应的数据源并不存在,每次针对此key的请求在缓存中获取不到,请求都会打数据源,这样的请求过多就会压垮数据库。

解决方案:采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据就会被bitmap拦截掉,从而减小了对底层存储系统的查询压力。

2、缓存击穿
key对应的数据源存在,但在redis中过期,若有针对该key的大量请求并发过来,就会从后端DB加载数据并回设到缓存,从而造成数据库压力过大而崩溃。

解决方案:
①设置key永不过期。最安全可靠,但会一直占有内存且无法获取最新数据。
②加互斥锁。在读取数据为NULL的时候,将尝试获取锁,若成功就重新从数据库加载数据并回设缓存,若失败就睡眠一定时间(保证数据回设缓存已经完成)重新从缓存中获取数据。代码参考:缓存击穿解决代码。

3、缓存雪崩
当缓存服务器重启或大量缓存集中在某一个时间段失效,这样在失效的时候也会给数据库带来很大的压力。缓存雪崩是针对很多个key,而缓存击穿是针对某一个key来说的。

解决方案:
①将缓存过期时间设置为一个随机值,避免缓存在同一时间过期;
②使用双缓存策略,设置原始缓存和备用缓存,原缓存失效时,访问备用缓存,备用缓存的失效时间设置得长一些。直到原始缓存在后台更新完成后,才会返回新缓存。

四、Redis持久化存储
redis是内存数据库,一旦重启后所有数据都会丢失,因此,需要将redis中的数据做持久化存储到磁盘。redis的持久化存储有以下两种方式:

RDB(Redis Data Base):
按照一定的时间周期执行快照,将内存中的数据保存到硬盘中。RDB是redis默认的持久化方式。

RDB的优点:
①适合冷备份。RDB是按时间周期存储,可以快速恢复之前某个时间段的数据。
②性能最大化。在同步数据的时候fork一个子进程去持久化,主进程继续处理命令。
③RDB数据恢复时的速度比AOF更高。

缺点:
①数据安全性低。RDB是间隔一段时间做持久化,如果这段时间redis发生故障,会发生数据丢失。
②RDB在生成数据快照时,若文件很大,客户端会暂停几毫米甚至几秒,若此时正在进行秒杀操作,性能会受到影响。

AOF(Append Only File):
将redis执行的每次写命令记录到单独的日志文件中,当redis重启时会从持久化的日志文件中恢复数据。

AOF的优点:
①数据安全性高。AOF每进行一次命令操作就会异步将数据记录到AOF中一次,若数据丢失,也只会丢失这一次的数据。
②rewrite模式。如用flushall命令误操作清空了所有数据,在后台没开始重写AOF文件之前,可以拷贝AOF日志文件,并删除其中的flushall命令。

缺点:
①同样的数据,AOF文件比RDB文件更大,恢复速度更慢;

RDB与AOF混合持久化
若单独使用RDB,可能会丢失很多数据;若单独使用AOF,数据恢复没有RDB快。因此,Redis4.0之后提供了混合持久化方式,也就是:采用RDB快照以一定频率执行保存数据,而在两次快照之间,使用AOF日志记录这期间的所有命令操作。

两种持久化存储方式如何选择
①如果你的业务场景需要很高的性能,或者宕机之后能够尽快的恢复,而对数据完整性的要求不是那么高,那么可以采用RDB持久化的方式。
②如果你的业务场景对数据完整性的要求很高,那么可以采用AOF持久化方式,而至于采用哪种回写策略,则取决于你对数据完整性的要求程度。
③如果你的业务场景既要兼顾性能,又注重数据完整性,那么可以采用混合持久化的方式。
④如果你对数据丢失无所谓,追求性能最大化的情况下,甚至可以禁用持久化。

五、过期key的删除策略
Redis是key-value型数据库,可以设置key的过期时间。在Redis中的过期策略有以下三种:
①定时删除: 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。
优点:保证内存被尽快释放;
缺点:若过期key很多,会需要占用大量CPU资源去处理过期数据,从而影响读取缓存的响应时间。
②惰性删除: 只有当访问这个key的时候,才会判断key是否过期,过期就删除。
优点:节省CPU资源;
缺点:若出现大量过期的key没有被访问,会占用大量内存;
③定期删除: 每隔一段时间,扫描一定数量设置了过期时间的key,并清除其中过期的key。
定期删除的性能介于定时删除和惰性删除之间。在内存占用方面,定期删除不如定时删除好;在CPU占用方面,定期删除不如惰性删除好。

为啥不扫描全部设置了过期时间的key呢?
假如Redis里面所有的key都有过期时间,都扫描一遍?那太恐怖了,而且我们线上基本上也都是会设置一定的过期时间的。全扫描跟你去查数据库不带where条件不走索引全表扫描一样,100s一次,Redis累都累死了。

Redis采用的key过期策略:惰性删除+定期删除。

六、内存淘汰策略
redis内存数据集大小上升到一定大小的时候,导致用于缓存的内存不足,就会施行数据淘汰策略。惰性删除+定期删除可能会残留大量的过期key,从而导致内存数据太大。

全局的键空间选择性移除
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

设置过期时间的键空间选择性移除
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值