11 | MySQL如何应对高并发(一):使用缓存保护MySQL
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何使用Redis作为MySQL的前置缓存来应对高并发读写压力。首先介绍了Redis的高性能特点,并讨论了在设计Redis缓存时需要考虑的数据不可靠性。文章详细讨论了更新缓存的最佳方式,提出了使用Cache Aside模式来避免并发读写导致的脏数据问题。此外,还强调了注意缓存穿透引起雪崩的问题,并提出了灰度发布和缓存预热等解决方案。总的来说,本文通过实际案例和技术原理,深入浅出地介绍了如何正确地使用Redis缓存来保护MySQL数据库,对于需要解决高并发读写问题的技术人员具有一定的参考价值。文章总结了使用Redis作为MySQL的前置缓存可以提升系统的并发上限,降低请求响应时延,并强调了Cache Aside模式更新缓存的最佳选择以及注意缓存穿透引起雪崩的问题。
《后端存储实战课》,新⼈⾸单¥59
全部留言(42)
- 最新
- 精选
- 李玥置顶Hi,我是李玥。 这里回顾一下上节课的思考题: 课后请你选一种你熟悉的非关系型数据库,最好是支持 SQL 的,当然,不支持 SQL 有自己的查询语言也可以。比如说 HBase、Redis 或者 MongoDB 等等都可以,尝试分析一下查询的执行过程,对比一下它的执行器和存储引擎与 MySQL 有什么不同。 谈一下我的理解: 我们拿一个分布式数据库Hive来看一下它的执行器和存储引擎。严格来说,Hive并不是一个数据库,它只是一个执行器,它的存储引擎就是HDFS加上Map-Reduce。在Hive中,一条SQL的执行过程是和MySQL差不多的,Hive会解析SQL,生成并优化逻辑执行计划,然后它就会把逻辑执行计划交给Map-Reduce去执行了,后续生成并优化物理执行计划,在HDFS上执行查询这些事儿,都是Map-Reduce去干的。顺便说一下,Hive的执行引擎(严格来说是物理执行引擎)是可以替换的,所以就有了Hive on Spark,Hive on Tez这些。2020-03-2135
- Geek_3894f9数据加版本号,写库时自动增一。更新缓存时,只允许高版本数据覆盖低版本数据。
作者回复: 👍👍👍
2020-03-211972 - GaGi对于Cache aside和read/write through而带来的数据不一致问题,工作中是这样解决: a写线程,b读线程: b线程:读缓存->未命中->上写锁>从db读数据到缓存->释放锁; a线程:上写锁->写db->删除缓存/改缓存->释放锁; 这样来保证a,b线程并发读写缓存带来的脏数据问题;
作者回复: 👍👍👍
2020-03-211641 - 丁小明老师,经常看到说用布隆过滤来解决缓存穿透问题,这个方案有实际的案例吗? 如果是真的可以那么怎么去操作呢? 先初始化所有可能存到缓存里面数据的key到一个足够大的布隆过滤器,然后如果有新增数据就就继续往过滤器中放,删除就从过滤器里面删(又看到说不用bit的话支持累加删除) 如果发现不在过滤器中就表示一定不存在,就无需查询了。如果在过滤器中也有可能不存在,这个时候在配合null值。 这个方案靠谱么,希望老师能解答一下
作者回复: 首先这是个经典的方案,靠谱是没问题的。它可以解决问题是,不用真正去查询数据集,就可以判断,请求的数据是不是,不在数据集内。如果不在就不用去查询数据集了。 不少数据库都内置了布隆过滤器来提升查询效率,比如HBase。 布隆过滤器的缺点就是有点复杂,实现难度还是挺大的。
2020-03-274 - 任鹏斌老师Cache Aside应该是先删缓存后更新数据库吧?先更新数据库的话一旦缓存删除失败了,就会产生脏数据
作者回复: 严格来说,在并发情况下,二种方式都有可能产生脏数据。Cache Aside Pattern建议,先操作数据库,再操作缓存。
2020-05-2143 - 王杰作者回复: 你可以参考一下“GaGi”同学的留言,用锁来解决并发问题。------------------------------------------------------老师,在读线程上写锁(说独占锁比较合适),是否跟MVCC相违背,MVCC不就是为了用来解决高并发带来的读写阻塞问题吗?我这边有两种解决思路不知可否:第一用版本控制,类似MVCC,第二种用Read/Write Through,写写并发在MVCC模式下依然是阻塞的,不算违背,所以只要把更新数据库与更新缓存放入统一事务中就行。读写并发不阻塞,是因为mysql用了快照读原因,那我们可以继续写线程更新缓存,读线程采用redis的setnx方式解决覆盖
作者回复: mvcc可以很好的解决读写冲突,但是对于写写冲突,要么加锁,要么引入冲突检测机制,否则就会导致写倾斜的问题。这个在23中有详细的说明。
2020-04-1853 - image如果缓存时有大量命中为null如何处理?如果命中null 也进行缓存,会导致缓存增长太快,容易被攻击 如果不缓存,又容易引起大量穿透
作者回复: 这种情况理论上也没有完美的解决方案,来说说实际上的一些处理经验。 首先,避免短时间大量人为的空值攻击,这个事儿应该在上层安全或者风控层面去解决。(即使无法判断是否空值攻击,至少要拦截住短时间大量的不正常访问请求) 剩余下来的就是业务上正常的查询返回空的情况,这种可能要从业务上来设计一下,尽量避免大量可能的空值查询。 以上2点做了之后,空值查询就会少多了,这个时候可以根据实际情况选择缓存空值,或者让空值穿透。
2020-03-263 - 1是不是model的话使用缓存,列表的话是不是不适合用缓存?列表应该怎么去缓存?
作者回复: 这个还是得看业务,很多列表也可以缓存的,比如说一些排行榜数据。
2020-03-23 - 蚂蚁内推+vCache Aside解决的只是并发写请求导致的缓存数据不一致问题。对于读写这种场景并没有彻底解决。 A:读,缓存穿透,查库。 B:写,更新数据库。 B:写,删除缓存。 A:读,回写缓存。导致不一致。 目前针对这种问题我们这边才去的方案是写请求后用MQ延迟删除缓存。老师有什么好的方法和实践吗?
作者回复: 你可以参考一下“GaGi”同学的留言,用锁来解决并发问题。
2020-03-212 - 往事随风,顺其自然老师有个问题请教你,我这边有个业务,合同编号,存在redis 🀄️和数据库中,每次先查redis 获取合同编号后面虚寒,然好加1⃣️,保存回去,外去更新数据库,做了数据库合同编号重复,检验,但是每次还是有合通编号重复的,请问这个怎么解决?市并发导致?
作者回复: 使用Redis命令INCR是可以保存原子性的。 如果是GET出来,在程序内加一,在SET回去,确实会存在并发问题。
2020-03-213