Redis使用场景介绍、分析
2020-02-29 本文已影响0人
Bricklayer
Redis使用场景
1、会话缓存
用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。
2、全页缓存
即使重启了Redis实例,因为有磁盘的持久化
3、队列
Redis作为队列使用的操作,就类似于本地程序语言(如oython)对list的push/pop操作。
4、排行榜/计数器
集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单
5、发布/订阅
在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统
Redis与MySQL的区别
这两者是内存和硬盘的关系,硬盘放置主体数据用于持久化存储,而内存则是当前运行的那部分数据,CPU访问内存而不是磁盘,这大大提升了运行的速度,当然这是基于程序的局部化访问原理;
推理到redis+mysql,它是内存+磁盘关系的映射,mysql放在磁盘,redis放在内存,这样的话,web应用每次只访问redis,如果没有找到数据,才去访问mysql
redis的过期策略以及内存淘汰机制
- 为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,当这个key过期就自动删除,虽然内存及时释放,但是十分消耗CPU资源,在大并发请求下CPU要尽可能的把时间都用在处理请求,而不是删除key,因此没有采用这一策略。 - 定期删除+惰性删除时如何的工作
定期删除:redis默认每100ms检查是否有过期的key,有过期的key则删除。需要说明的是redis不是每隔100ms将所有的key检查一次,而是随机抽取进行检查。因此,如果只采用定期策略,会导致很多key到时间没有删除
惰性删除:你在获取key的时候,redis会检查一下,这个key如果设置过期时间,那么是否过期了?如果过期,此时就删除。 - 内存淘汰机制
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(推荐使用)
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。(应该也没人用吧,你不删最少使用 Key,去随机删)
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。(不推荐)
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。(依然不推荐)
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。(不推荐)
使用redis有什么缺点/常见问题
- 缓存和数据库双写一致性问题
我们所做的方案从根本上来说,只能降低不一致发生的概率。因此有强一致性要求的数据,不能放缓存。首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败问题,提供一个补偿措施即可,例如利用消息队列 - 缓存雪崩问题
即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:
给缓存的失效时间,加上一个随机值,避免集体失效;
使用互斥锁,但是该方案吞吐量明显下降;
双缓存,我们有两个缓存,缓存A和缓存B,缓存A的失效时间为20分钟,缓存B不设失效时间,自己做缓存预热操作;
然后细分以下几个小点:从缓存A读数据库,有则直接返回;A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程,更新线程同时更新缓存A和缓存B。 - 缓存穿透问题
即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方案:
利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读取数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
提供一个能迅速判断请求是否有效的拦截机制,比如:利用布隆过滤器,内部维护一系列合法有效的key。迅速做出判断,请求所携带的key是否合法有效,如果不合法,则直接返 - 缓存并发问题