MySQL应对高并发之Redis缓存

Wesley13
• 阅读 613

高并发

高并发(High Concurrency)是指系统运行过程中的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问收到大量请求,例如淘宝双十一、京东618类的活动。该情况的发生会导致系统在这段时间内执行大量操作(对资源的请求、数据库的操作等)。

高并发相关常用的一些指标有:响应时间、吞吐量、每秒查询率QPS、并发用户数。
「响应时间」:系统对请求做出响应的时间。例如系统处理一个http请求需要600ms,这个600ms就是系统的响应时间。
「吞吐量」:单位时间内处理的请求数量。
「QPS」:每秒响应请求数。
「并发用户数」:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线的用户量一定程度上代表了系统的并发用户数。

简单来说,高并发的基本表现就是系统在单位时间内能够同时处理的请求数。高并发没有具体的范围规定多少并发算是高并发,比如你开发的系统最大并发是1000,那么来了1001的并发量对你来说就是高并发,但是这个并发量放在淘宝上,简直什么都算不上。

如果高并发处理不好,不仅会降低用户的体验度(请求响应时间过长等),同时可能导致系统宕机、停止工作等。

使用缓存

大家都知道MySQL加上Redis是一对儿经典的组合。使用Redis作为MySQL的前置缓存,可以为MySQL挡住大部分查询请求,可以很大程度上缓解MySQL并发请求的压力。Redis是一个使用内存保存数据的高性能K-V数据库,它的高性能主要来自于:「简单的数据结构」「使用内存存储数据」。但是我们需要知道的是内存本身就是一种易失性存储,所以使用Redis不能保证数据可靠存储。从设计上来说,Redis牺牲了数据可靠性,换取了高性能。但也正是这些特性,使得Redis特别适合用来做MySQL的前置缓存。

即使只是把Redis作为缓存来使用,我们在设计Redis缓存的时候,也必须要考虑Redis的这种「数据不可靠性」,或者换句话说,我们的系统在使用Redis的时候,要能兼容Redis丢数据的情况,做到即使Redis发生了丢数据的情况,也不影响系统的数据准确性。

关于缓存更新策略,使用的多的也就是「Read/Write Through模式」「Cache Aside模式」「Read/Write Through模式」 在查询数据的时候,先去缓存中查询,如果命中缓存那就直接返回数据;如果没有命中,那就去数据库中查询,得到查询结果之后把数据写入缓存,然后返回。在更新数据的时候,先去更新数据库,如果更新成功,再去更新缓存中的数据。 MySQL应对高并发之Redis缓存

我们想一下,这样使用缓存的方式有没有问题?绝大多数情况下可能都没问题。但是,在高并发的情况下,有一定的概率会出现「脏数据」问题,缓存中的数据可能会被错误地更新成了旧数据。

比如,对同一条记录,同时产生了一个读请求和一个写请求,这两个请求被分配到两个不同的线程并行执行,读线程尝试读缓存没命中,去数据库读到了订单数据,这时候可能另外一个写线程在处理写请求的过程中,先后更新了数据和缓存,这个时候就有问题了,拿着旧数据的第一个读线程又把缓存更新成了旧数据,脏数据也就产生了。

这是一种情况,还有比如两个线程对同一个条订单数据并发写,也有可能造成缓存中的脏数据,而且出现脏数据的概率是和系统的数据量以及并发数量正相关的,当系统的数据量足够大并且并发足够多的情况下,这种脏数据几乎是必然会出现的。那么有没有可能避免或者减少脏数据的产生呢,是有的,接下来介绍另外一种模式。

「Cache Aside模式」 Cache Aside模式和上面的Read/Write Through模式非常像,它们处理读请求的逻辑是完全一样的,唯一的一个小差别就是,Cache Aside模式在更新数据的时候,并不去尝试更新缓存,而是去删除缓存。

MySQL应对高并发之Redis缓存

使用这种模式来更新缓存,可以非常有效地避免并发读写导致的脏数据问题,虽然Cache Aside模式相较于Read/Write Through模式,降低了脏数据产生的概率,但是在高并发下更容易造成缓存穿透引起雪崩。

总结

使用Redis作为MySQL的前置缓存,可以非常有效地提升系统处理高并发的能力,降低请求响应时间。绝大多数情况下,使用Cache Aside模式来更新缓存都是最佳的选择,相比Read/Write Through模式更简单,还能大幅降低脏数据的可能性。特别注意的是,大量缓存穿透引起雪崩的问题,你需要针对具体业务场景来选择合适解决方案。

最后,感谢女朋友在工作和生活中的包容、理解与支持 !

MySQL应对高并发之Redis缓存

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这