分布式锁

分布式锁本质就是在Redis中设置一把锁,当别的进程也要上锁时,入股发现已经被上锁了,就需要放弃或者重试。

上锁一般使用set(set if not exits)指令,只允许一个客户端上锁,用完之后使用del指令释放。

但是如果成功上锁后,程序出现问题,无法执行del,那么锁将永远不能释放。对此,可以将锁设置一个过期时间,set [key] [value] ex [timeout] nx,这个指令是将setnxexpire组合在一起的原子指令,这就是分布式锁的核心。

Redlock算法

加锁时,会向过半的节点发送set(key, value, nx = True, ex = xxx)指令,只要过半节点set成功,就认为加锁成功

释放锁时,需要向所有节点发送del指令。

因为Redlock需要向多个节点进行读写,会比单实例的Redis性能下降一些。

缓存穿透

缓存穿透是指查询一个一定不存在的数据,因为缓存中也无该数据的信息,则会直接去数据库层进行查询,从系统层面来看像是穿透了缓存层直接达到DB,从而称为缓存穿透。

解决:

  • bloom filter:类似于哈希表的一种算法,用所有可能的查询条件生成一个bitmap,在进行数据库查询之前会使用这个bitmap进行过滤,如果不在其中则直接过滤,从而减轻数据库层面的压力。
  • 空值缓存:一种比较简单的解决办法,在第一次查询完不存在的数据后,将该key与对应的空值也放入缓存中,只不过设定为较短的失效时间,例如几分钟,这样则可以应对短时间的大量的该key攻击,设置为较短的失效时间是因为该值可能业务无关,存在意义不大,且该次的查询也未必是攻击者发起,无过久存储的必要,故可以早点失效。

缓存雪崩

缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

解决:

  • 交错失效时间:这种方法时间比较简单粗暴,既然在同一时间失效会造成请求过多雪崩,那我们错开不同的失效时间即可从一定长度上避免这种问题,在缓存进行失效时间设置的时候,从某个适当的值域中随机一个时间作为失效时间即可。
  • Hystrix + 本地缓存:这是当发生雪崩时的应对方法

缓存击穿

缓存击穿实际上是缓存雪崩的一个特例,在热点的缓存到达失效时间时,此依然有大量的请求到达系统,没有了缓存层的保护,这些请求同样的会到达DB从而可能引起故障。击穿与雪崩的区别即在于击穿是对于特定的热点数据来说,而雪崩是全部数据。

解决: