一、使用场景
结合简历上的业务回答:
1.缓存(穿透、击穿、雪崩、双写一致、持久化、数据过期策略、数据淘汰策略)
1.1 缓存穿透
定义:查询一个不存在的数据,mysql查询不到数据也不会写到缓存中,导致每次请求都要查询数据库,有可能导致数据库压力增大而宕机。
解决方案:
1.如果MySQL查询结果为空,则将空结果存到缓存中,{key:1,value:null}
2.布隆过滤器:
原理:当查询一个id为1的值时,布隆过滤器通过多个哈希函数对id值进行计算,获得hash值,将位图中hash值对应的位置改为1。下一次查询数据时,使用相同hash函数获取hash值,判断对应位置是否都为1。
1.2 缓存击穿
当一个热点数据的key到期时,恰好这个时间对这个key有大量的并发请求过来,这些并发请求可能会瞬间把DB压垮。
解决方案:
1.添加互斥锁:只有一个线程拥有互斥锁,进行缓存重建,其他线程等待。强一致、性能差
2.逻辑过期:一个线程拥有互斥锁,进行缓存重建,其他线程先返回当前结果。高可用、不保证数据绝对一致。
1.3 缓存雪崩
定义:同一时段大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案:
1.给不同的key的TTL添加随机值
2.利用redis集群提高服务的可用性(哨兵模式、集群模式)
3.给缓存业务添加降级限流策略(ngxin、spring cloud gateway)
4.给业务添加多级缓存(guava、caffeine)
1.4 双写一致性(业务+逻辑)-如何保持redis和MySQL数据的同步呢?
可以用互斥锁,为每个线程的缓存过程添加互斥锁。进一步提高效率,可以使用共享锁和排他锁,在读数据时使用共享锁,其他线程可以共享读操作,在写数据时使用排他锁。
我们的项目中,是把热点数据存入到了缓存中,虽然是热点数据,但是实时性要求没有那么高,所所以,我们当时采用的是异步的方案同步数据。
1.5 持久化(RDB、AOF)
。。。待更新