Redis缓存和数据库一致性、雪崩、穿透、热点key、big key

一、实时同步

对强一致要求高的,应采取实时同步方案,即查询缓存查询不到再从DB查询,保存到缓存;更新缓存时,先更新数据库,再将缓存的设置过期(建议不要去更新缓存内容 直接设置缓存过期)
@Cacheable:查询时使用,注意Long类型需要转换为String,否则会抛出异常
@CachePut:更新时使用,使用这个注解,一定会从DB查询数据
@CacheEvict:删除时使用
@Caching:组合用法

二、异步队列

对于并发度高的,可以采用异步队列来同步,可以采用kafka等消息中间件处理消息生产和消费

用户进行高并发(读写)—>走Redis
MYSQL—>数据需要同步
定时任务:每天一个时间点将Redis中数据得到,更新到MYSQL

消息队列:RabbitMQ RocketMQ Kafka
作用:异步、流量销峰

三、使用阿里同步工具canal

四、采用UDF自定义函数的方式

面对MYSQL的API进行编程,利用触发器进行缓存同步,但UDF主要是C/C++实现 学习成本高

穿透

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透

判断Redis是否存在KEY
如果不存在,查询MYSQL(查询结果为空) 特定值L"NULL"(这个null是个字符串),并且将结果存入Redis
user:1:“NULL”
如果存在,直接查询Redis返回

这样会 让人恶意攻击 一直发送请求来查询 然后NULL就会快速的充满内存

user id(将MYSQL表中User 中所有ID全部查询出来 存到Set集合中)
controller中:
if(set集合是否存在 id){
存在:查询MYSQL并存入Redis
不存在:直接返回客户端错误
}

解决方法:
持久层查询不到就缓存空结果,查询时先判断缓存中是否exists(key),如果有直接返回空,没有则查询后返回,注意insert时需要清除查询的key,否则即便DB中有值也查询不到(当然也可以设置空缓存的过期时间)
1.不管数据实际上存不存在,都把这个键存到缓存中(有效期设置的短一些,比如一分钟到三分钟),然后值设置为一个特定值,业务中如果获取到的结果是这个特定值,则报错返回
2.是使用Redis的布隆过滤器(Bloom Filter),将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被bitmap过滤掉,从而避免了对底层存储系统的查询压力

URL安全(参数安全)(访问渠道非正常访问或者恶意拼凑参数方式访问)
为防止用户在前端输入一些不存在的ID
可以对ID进行加密
如果某个原文经过加密算法加密后得到密文,密文哪怕只经过细微的变更,再进行密文解密的时候都会发送异常报错

雪崩

缓存大量失效,引发大量查询数据库

解决方法:
用锁/分布式锁或者队列串行访问
缓存失效时间均匀分布

如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
这个没有完美的解决办法,但是可以分析用户行为,尽量让失效时间点均匀分布,大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线程写,从而避免失效时大量的并发请求落到底层存储系统上

1.加锁排队,限流–限流算法
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
简单来说,就是缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法

SETNX,是SET if not exists 的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果

2.数据预热
可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀

热点key(缓存击穿)

热点key:某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃

解决方法
1.使用锁,单机用synchronized,lock。分布式用分布式锁
2.缓存过期时间不设置,而是设置在key对应的value里,如果检测到存的时间超过过期时间则异步更新缓存
3.在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作
4.设置标签缓存,标签缓存设置过期时间,标签缓存过期后,需要异步更新实际缓存

可以对热点key用双重检测锁:
在这里插入图片描述

缓存倾斜

又叫热点key倾斜,我们的redis一般都是集群,然后每个key(一致性hash算法)会落到某个集群的主机上面,如果出现了热数据
比如像热点新闻、商城秒杀等

这样导致大量用户突然高并发访问这个热点key所在的那台缓存服务器,导致某台服务器集中大量请求导致倾斜

解决方案
1.本地客户端缓存
将一些特别热点的key直接放在客户端进行存储,设置过期时间,过期后再从后台(Redis)查询,或者存储在二级缓存,比如jvm中
2.利用分片算法特性,对key进行打散处理
可以将这个热点key复制出多个子key,每个key的value值一样,查询的时候使用hash取模算法,将压力分摊到不同的节点

big key

数据量大的key,由于数据大小远大于其他key,导致经过分片后,某个具体存储这个big key的实例内存使用量远大于其他实例,造成内存不足,拖累整个集群使用,big key在不同业务上

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值