注:转载请注明出处。

当我们访问网站时服务器正常的处理流程应该是:数据先从缓存取,没有就去查询数据库,然后将查询到的结果放缓存一份。

但当高并发情况下缓存会出现很多问题或者安全隐患。

1.缓存穿透

查询数据库中不存在的数据: 因为数据库中不存在,所以缓存中肯定没有,所以按照上面的流程来说,缓存就没意义了,所有的请求都会落到数据库上面,如果高并发的话,数据库就崩溃了。

解决方案:

我们一般查询都是主键查询(其他查询一般走搜索), 主键如果是自增的,可以将当前的数据库的主键最大值放缓存,然后修改流程为先查询缓存,有的话返回,没有的话先比较查询的主键和缓存中放的最大值,小于等于最大值就代表在数据库,然后继续后面的流程。
如果主键不是自增的,就将所有的主键取出来放redis的set,然后上面流程修改为 为先查询缓存,有的话返回,没有的话先判断查询的主键在不在set中,在就查询数据库,不在返回。

2.缓存穿刺(击穿):

缓存中某一条热点数据因为某些原因失效了或者不见了(反正就是缓存中没有这个数据),如果这个时候高并发访问这个数据,根据上面的防穿透原则,发现数据在数据库,这个时候会有不少并发去查询数据库(因为查询到数据并放入缓存需要时间,在这个时间内可能会有不少并发),数据库可能也会瘫痪。

解决方案:

既然是查询都相同数据,就没必要都去查询,只要有一个人去查询数据库,并放到缓存,其他人再从缓存中取就行,所以从数据库查询的地方加分布式锁,拿到锁的人去查询数据,拿到后放到缓存,拿不到的人等待唤醒,唤醒后从缓存中取就行,这样不管高并发还是低并发的穿刺都会被解决,当然前面导致数据丢失的问题也要去根据具体情况解决。

3.缓存雪崩:

缓存中大量数据在短时间内到期,然后短时间内不同人在访问这些数据,导致高并发(穿刺是某一条数据的高并发,雪崩是很多不同数据最终高并发,当然雪崩中可能会包含穿刺的数据)访问数据库。

解决方案:

这个最简单,我们只需要设置不同的到期时间范围就能避免雪崩问题。

4.缓存倾斜:

上面三种情况大部分人都了解过,但缓存倾斜就好多听都没听过了。

我们的redis一般都是集群,然后每个key根据算法会落到某个集群的主机上面,如果出现了高热数据,比如像新浪微博的热点新闻, 他们的key是固定的,所以这个key一定是在某个服务器上面的,这个时候如果高并发的话,大量的请求会涌向集群中的某台服务器,而我们使用集群的目的本来是尽量平分请求的,现在大量请求集中到某台服务器导致了倾斜,甚至可能导致缓存服务器崩溃等。

解决方案:

产生的原因是大量请求去了一个机器,那我们只要让他去不同机器就行了。

所以两种方案. 1: 我们的redis某个主机下面肯定有从机,所以我们可以做读写分离,数据查询分配到不同从机上面,所以我们只需要做个注册中心,里面放上对应的从机列表,应用服务器在查询数据的时候先获取到从机的列表,然后从里面查。
2: 我将数据放到不同主机上,因为相同的key一定在某个机器,所以我可以将这个热数据存几个不同的key,比如奔驰车,原始key是66bz,那我们可以放66bz:1 66bz:2 …..不同的key,不同的key放的数据一样,然后利用不同的key会被放在不同服务器上面这个特点来平分请求,那取的时候取哪个key呢,我们可以给应用服务器加标记,比如第一个机器是1 第二个是2 以此类推,应用服务器取数据之前, 发现这个数据是热点数据,那么根据key加上自己的标记 然后根据这个key去取数据。

视觉中国警告:转载注明出处

发表评论

电子邮件地址不会被公开。 必填项已用*标注