电商缓存问题

电商项目中 必不可少的就是缓存 而通常使用redis作缓存

基本实现:先读缓存,没有从数据库查,存缓存一份 有直接返回

如何保持 mysql数据库 和redis缓存一致性问题

读取缓存数据一致性一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题

1.双写模式: 写mysql 写缓存redis 无论先写哪一个 都会有问题

1.1先写 redis

写成功 再写mysql 此时mysql写入失败 数据就不一致

写失败 不用玩了 写mysql成功 那就不一样了

1.2 先写 mysql 成功 再写 redis 程序发生异常或者事务提交失败 mysql会回滚 但是redis不会 数据仍然不一样。

2.失效模式:就是先清空缓存 原因就是我更新mysql之前 其他用户把旧数据又读到缓存了

先删除缓存,后更新数据库:当发生「读+写」并发时,还是存在数据不一致的情况。

2.1 先清空redis缓存 再写mysql 再读取mysql到redis 高并发下 a用户执行再写还没有写完的时候 这个时候b来读缓存 就会从旧的数据加载缓存 然后a写成功了 mysql就变为新的数据了

先更新数据库,后删除缓存:

2.2 先写mysql 写成功 删除缓存 还没提交事务 此时并一个线程过来 读缓存 发现没有 从旧数据读 然后数据又不一致

3.双删模式 延迟双删 解决其他用户把旧数据又读到缓存了 再删除一次

更新完mysql 提交事务之前 发消息mq 删除缓存 或者aop思想 后置通知里面 删除缓存 总之就是先提交更新mysql事务 再删除缓存

3.1 先清空缓存 解决异步的时效性 和可靠性

3.2写mysql

3.3 发送异步消息

3.4提交事务

3.5获取消息异步删除缓存

4.canal中间件

订阅数据库变更日志,再操作缓存,具体来讲就是,我们的业务应用在修改数据时,「只需」修改数据库,无需操作缓存。

那什么时候操作缓存呢?这就和数据库的「变更日志」有关了。

拿 MySQL 举例,当一条数据发生修改时,MySQL 就会产生一条变更日志(Binlog),我们可以订阅这个日志,拿到具体操作的数据,然后再根据这条数据,去删除对应的缓存。

这时我们换个角度思考一下,我们引入缓存的目的是什么?

性能

一旦我们决定使用缓存,那必然要面临一致性问题。性能和一致性就像天平的两端,无法做到都满足要求。

所以如果非要追求强一致,那必须要求所有更新操作完成之前期间,不能有「任何请求」进来。

虽然我们可以通过加「分布锁」的方式来实现,但我们要付出的代价,很可能会超过引入缓存带来的性能提升。

所以,既然决定使用缓存,就必须容忍「一致性」问题,我们只能尽可能地去降低问题出现的概率。

同时我们也要知道,缓存都是有「失效时间」的,就算在这期间存在短期不一致,我们依旧有失效时间来兜底,这样也能达到最终一致。

1、想要提高应用的性能,可以引入「缓存」来解决

2、引入缓存后,需要考虑缓存和数据库一致性问题,可选的方案有:「更新数据库 + 更新缓存」、「更新数据库 + 删除缓存」

3、更新数据库 + 更新缓存方案,在「并发」场景下无法保证缓存和数据一致性,且存在「缓存资源浪费」和「机器性能浪费」的情况发生

4、在更新数据库 + 删除缓存的方案中,「先删除缓存,再更新数据库」在「并发」场景下依旧有数据不一致问题,解决方案是「延迟双删」,但这个延迟时间很难评估,所以推荐用「先更新数据库,再删除缓存」的方案

5、在「先更新数据库,再删除缓存」方案下,为了保证两步都成功执行,需配合「消息队列」或「订阅变更日志」的方案来做,本质是通过「重试」的方式保证数据一致性

6、在「先更新数据库,再删除缓存」方案下,「读写分离 + 主从库延迟」也会导致缓存和数据库不一致,缓解此问题的方案是「延迟双删」,凭借经验发送「延迟消息」到队列中,延迟删除缓存,同时也要控制主从库延迟,尽可能降低不一致发生的概率

缓存常见问题:读并发问题

缓存穿透、缓存击穿、缓存雪崩

缓存穿透:记忆:(穿透就是都击穿) 大量请求访问不存在的数据 缓存中没有 然后全部打到mysql上 mysql服务器直接就挂了

解决方案:缓存为null的数据 但是多了就会影响内存 ,缓存时间一般不超过五分钟。布隆过滤器

缓存击穿:(击穿就是一个点击穿) 就是某一个热点数据,在某时刻刚好失效了,同时又有大量请求过来,就会导致请求数据库,导致mysql服务器挂掉。

解决:保证热点数据不超时 ,一直存缓存 分布式锁(互斥锁)

缓存雪崩:过期时间相同,导致大量缓存数据同时过期,此时大量请求同时访问这些数据,就会直达mysql数据库,导致mysql宕机

解决方案:给缓存时间添加随机值

java用lua脚本。DefaultScriptRedis一定要指定lua脚本返回结果集,bug。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值