前言:
项目开发中使用redis会遇到的问题,并且你是怎么解决的?
一.缓存雪崩:
- 概念:缓存在长期应用的系统中,存储了大量的高并发访问数据,一旦这些数据突然批量消失,访问吞吐的并发,到达数据库,导致数据库崩溃。
- 自我理解:由于在高并发的请求场景中,大量数据是缓存在数据库中的,数据库压力小,当大量缓存数据同时消失时,这些大量请求将同时访问数据库,数据库扛不住压力,将会崩溃。
- 原因:1.缓存数据超时时间保持一致,当时间到达时数据将会同时消失。 2.redis分片宕机,短时间造成雪崩。
- 解决方案:1.超时时间不要集中在一起,加入随机缓存时间。2.第二种代码不提供解决方案,最多降级处理(不重要的数据降级),
二.缓存击穿:
- 在高并发时,当一个key突然变成了爆款(热销商品),在不停的高并发,当这个key失效的瞬间,持续的高并发就会击穿缓存,直接请求数据库并存储到缓存中,导致性能下降。
解决方案:
- 永不过期:将爆款商品过期时间设置为永久,当然有些爆款是我们始料不及的,那我们也可以写一个方法,当请求量达到一定的时候,修改key的过期时间。
- 加锁排队-同步锁:思路就是当大量线程访问已经失效的缓存时,我们在查询数据并设置到缓存的方法里面加上同步锁,只让一个线程进行访问,这个线程进来后访问数据库,并存储到redis,之后的线程就可以访问redis里面的缓存数据了。
- 加锁排队-分布式锁:
三.缓存穿透:
- 数据库中数据不存在,缓存中的数据也不存在,每回都去请求数据库,这种的一般都是攻击者,访问不存在的数据如id为-1或id特别大(不存在的数据),导致数据压力特别大。
解决方案:
- 参数校验,不合法的参数不让访问
- 对于数据库查询为null的(临时 数据),也存储到缓存(redis可能会因为大量故意访问,出现大量null数据)
- 引入过滤器(布隆过滤器),拦截根本不存在的数据
- 布隆过滤器:提前将数据库数据同步到过滤器中,如果请求过来的数据不存在,则拦截
- 缺点:批量新增到布隆,也可以增量新增.不能删除(重新清空预热). 判断存在的概率,有可能误判的.比如100万条 判断100万条存在 200条实际是不存在的
- 解决:布隆过滤器 + 哈希表:可以将布隆过滤器与哈希表结合使用。布隆过滤器用于快速判断一个元素是否存在,而哈希表用于存储实际的元素数据。当布隆过滤器判断一个元素可能存在时,再通过哈希表进行进一步验证。
四.缓存一致性:
- 批量一致性:一次性处理大批数据
- 解决方案:预热同步,同步刷新
- 增量一致性:一次处理一条数据,几条数据相比于千万百万的数据,非常小的数据量
- 解决方案:采用双删(延迟双删)
延迟双删和双删的区别,就是第二次删除redis的时候,是否要先等待1-3秒.
redis分布式:架构演变
单机:
优点:搭建简单
缺点:读写瓶颈
使用场景: 不会在线上(test,prod)系统使用(除非没什么并发),会搭建在开发场景.
哨兵集群:
优点: 管理主从的集群.可以解决单点故障问题
缺点: 不能实现分布式,不能实现高吞吐,高并发,大量数据存储.
使用场景: 考虑高可靠性的,但是没有高并发的场景.
自我理解:
哨兵会实时发送心跳检测主节点的健康状态,判断主节点是否工作,当一个哨兵节点发现主节点不工作时,将会通知其他节点进行心跳检测,当超过三个哨兵节点发现主节点不工作时,将会从从节点中选举出新的主节点。(主节点会实时同步数据到从节点,一个主节点多个从节点)
cluster: 多个主从组成的集群,引入分布式计算
优点: 高吞吐,高并发,高数据存储容量
缺点: 数据设计key值如果不合理,批量读写会导致性能极大浪费.(没有批量需求的业务,碰不见)
使用场景: 高并发 高吞吐场景 6个redis 总吞吐量保守估计 4C4G(6台) 服务器中10万/s
自我理解:
多个主从节点组成,当一个主节点宕机时,其他主节点会选举出该宕机的主机点下的其他从节点,成为新的主节点。但是如果存活主节点不足半数时将无法给宕机的节点,选定新的主节点。