Redis过期策略和淘汰机制:
1.过期策略:redis set key的时候设置一下expire time,就是过期时间,指定多久key过期。到期后缓存就失效了。
redis定期删除和惰性删除:
过期删除:redis默认是每隔一段时间(0.1s)就随机抽取一些设置了过期时间的key值,检查是否过期,过期就删除
惰性删除:redis在获取某个key进行查询时,就会检查一下是否已经处于过期时间,是则就删除掉。
2.内存淘汰机制:
当redis 的内存占用过多内存或者快达到内存的上限一定比例的时候就会触发redis内存的淘汰策略:
1.noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用
2.allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
3.allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般也没人用
4.volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
5.volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
6.volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
注:一般都是采用第二种策略allkeys-lru,因为删除最近最少使用key基本符合我们的业务要求
redis数据一致性问题:
对于读多写少的高并发的场景,经常使用Redis。但是存在一些数据一致的问题:
redis中的数据和数据库的数据不可能保证事务达到一致性,所以在实际的应用中,需要基于业务场景尽可能的降低
出现不一致的问题的概率。
解决方案:
更新缓存/缓存失效。
1.更新缓存不但要写入数据库还需要同步更新缓存数据:如果更新缓存的代价很小,那么可以先更新缓存,这个代价很小的意思是不需要很复杂的计算去获得最新的余额数字。
2.缓存失效表示更新数据库,然后删除缓存的Key值:如果是更新缓存的代价很大,意味着需要通过多个接口调用和数据查询才能获得最新的结果,那么可以先淘汰缓存。淘汰缓存以后后续的请求如果在缓存中找不到,自然去数据库中检索。
当采用让缓存失效,存在两个情况,先更新数据库再让缓存失效,还是先缓存失效,
再更新数据库?:更新数据库和缓存的两个操作无法做到原子性,所以我们需要根据当前业务的场景的容忍性来
所以我们需要根据当前业务的场景的容忍性来选择。也就是如果出现不一致的情况下,哪一种更新方式对业务的影响最小,就先执行影响最小的方案。
最终一致性的解决方案:
对于分布式系统的数据最终一致性问题,我们可以引入消息中间件(),对于失败的缓存更新存入对应的 broker,并对其进行订阅,当有消息来了,我们可以对由于网络等非程序错误的异常缓存更新进行重试更新。
缓存雪崩:
缓存雪崩指的是设置缓存时采用了相同的过期时间,导致缓存在某一个时间同时失效,或者缓存服务器宕机导致缓存全面失效,请求全部转发到DB层,瞬间压力过大,导致崩溃。
解决方式:
1. 对缓存的访问,如果发现从缓存中取不到值,那么通过加锁或者队列的方式保证缓存的单进程操作,从而避免失效时并并发请求全部落到底层的存储系统上;但是这种方式会带来性能上的损耗
2. 将缓存失效的时间分散,降低每一个缓存过期时间的重复率
3. 如果是因为缓存服务器故障导致的问题,一方面需要保证缓存服务器的高可用、另一方面,应用程序中可以采用多级缓存
缓存穿透:
缓存穿透是指可能黑客通过手段查询一个根本不存在的数据,缓存和数据库都不会查询到的。