redis异常测试

1、更新KEY异常,先删再存还是直接覆盖

案例:

查询退改XX起原来线上是每8小时刷新一次缓存,查询去每8小时去查退改签库拉退改签数据,根据航司作为KEY存到Redis中,再放到各机器内存中使用
这次调整为退改签有改动就发mq消息给查询,查询收到消息,则重新去拉全量数据

开发设计时有变动就全量更新,且是先删除后存入,这样可能存在大量请求过来没有拿到数据

推动修改放案:从退改数据库拉数据之后,先和Redis原来的key(航司)做hash比对,如果原来的Redis多了,则清除,剩下的再做更新操作

2、KEY删除和丢失区分

案例:

政策先同步到Redis,再发消息给数据同步build站,build站收到消息后,会去拿Redis的数据更新到mongodb,如果没有查到key会做删除操作

如果Redis 数据丢失,key不会存在,则会造成误删

解决方案:

删除key时,生成key,数据为[],查到KEY的数据为[]则删除数据;数据丢了,不生成KEY,没查到KEY去实时调接口查

build收到消息后,去更新mongdb,如果查到的key是[],则删除该条航线

build收到消息后,去更新mongdb,如果没查到该key,则在去实时调官网DSF接口

3、KEY 过期策略不当造成内存泄漏

TTL KEY TTL过期时间为秒

当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以秒为单位,返回 key 的剩余生存时间。

大多数业务redis都会设置过期时间,key过期时如何清理的,也需要了解下

惰性清理(被动清理)

某个KEY过期后,不会立马被删除,下次使用时检查时候过期,过期就删除

缺点:浪费内存,长期不访问没法清理,垃圾数据过多,可能引起内存泄漏

定期清理(主动清理)

Redis会定期主动淘汰一批已过期的key(随机抽取一批key检查)

缺点:KEY已过期,仍未清理,需要等待JOB扫

内存淘汰机制

当前已用内存超过maxmemory限定时,触发主动清理策略:大多数会设置一个阀值,达到一定阀值自动扩容,除非自动扩容失败,则会出问题

noeviction(默认策略):当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

目前公司一般采取惰性和定期清理配合使用

4、查询Redis异常,是否实时调接口/数据库

很多情况redis只是做一个缓存机制,如果redis异常或者未取到数据,是否有实时获取数据的兜底方案,需要考虑

5、Redis击穿

某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。

解决方案:可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据;或者用Hash方法对比KEY进行增删改

6、缓存雪崩

对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。

解决方案:

事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据

7、缓存穿透

对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。

解决方案:

每次系统 A 从数据库中只要没查到,就写一个空值到缓存里去,比如 set -999 UNKNOWN。然后设置一个过期时间,这样的话,下次有相同的 key 来访问的时候,在缓存失效之前,都可以直接从缓存中取数据。

8、Redis锁,使用不当造成锁不能释放,陷入死锁

目前常用的2种锁:

1)SET Key UniqId Seconds

仅在单实例的场景下是安全的,不用setnx+expire+del 中间断了仍可能造成死锁;不用SET Key UnixTimestamp Seconds NX,高并发可能存在相同时间戳

2)分布式Redis锁:Redlock

此种方式比原先的单节点的方法更安全

安全性:在同一时间不允许多个Client同时持有锁。
活性死锁:锁最终应该能够被释放,即使Client端crash或者出现网络分区(通常基于超时机制)。
容错性:只要超过半数Redis节点可用,锁都能被正确获取和释放。

案例:

综合推荐获取航班动态的redis数据时,某个航线没有推荐出来,高并发生成相同时间戳redis的KEYLOCK,redis解锁失败导致

9、Redis持久化

当Redis数据需要长久有效时,需要考虑是否做RDB和AOF持久化,一般RDB和AOF配合使用,但做持久化,会影响性能,目前做持久化的很少见

比如如来Redis数据是长久有效的,但却为了响应快不影响性能,未做持久化;采用了其他的降级方案Hbase,以及业务的兜底

10、缓存与数据库双写时的数据一致性

一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况,最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况
串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求。
还有一种方式就是可能会暂时产生不一致的情况,但是发生的几率特别小,就是先更新数据库,然后再删除缓存。

并行写数据库和缓存,可以加个事务都写成功才成功,有一个环节失败了就回滚事务,全失败

问题场景

描述

先写缓存,再写数据库,缓存写成功,数据库写失败

缓存写成功,但写数据库失败或者响应延迟,则下次读取(并发读)缓存时,就出现脏读

先写数据库,再写缓存,数据库写成功,缓存写失败

写数据库成功,但写缓存失败,则下次读取(并发读)缓存时,则读不到数据

需要缓存异步刷新

指数据库操作和写缓存不在一个操作步骤中,比如在分布式场景下,无法做到同时写缓存或需要异步刷新(补救措施)时候

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值