社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

Redis:MySQL算老几?

码农翻身 • 5 年前 • 523 次点击  

前言:上一篇《MySQL:缓存算什么东西?》里挖了一个坑,也有很多人说没看过瘾,今天接着写,把坑填上,不过得把视角换一下,让Redis上台发言。

我知道MySQL看我不顺眼,不就是他的好基友Tomcat不怎么搭理他了吗? 这能怪我? 谁让他那么慢?


张大胖把我Redis安排到这个系统中来,那就是为了提升系统的响应速度,我把数据都暂时放到了内存中,每当Tomcat需要的时候直接拿走就是了,都不用联系MySQL。只有我这里没有数据的时候Tomcat才会给MySQL说一句:“哥们,把这个SQL执行一下啊,把数据告诉我!”



MySQL不死心,不断使坏,总想着把我给干掉,恢复他昔日的荣耀和地位。可历史的车轮滚滚向前,想逆潮流而动,无异于螳臂挡车啊!


有时候我真想把我缓存中的数据删除,让高并发的访问都压到他那里去, 累死他! 可一想到自己的职业道德,尤其是张大胖那可怜样,还是忍了吧。


黑客攻击?


这一天中午,Tomcat发现流量有些异常,之前大部分的数据我都可以处理,这一次大量的请求在我Redis这里竟然获取不到数据! Tomcat被迫向MySQL求援:“哥们,这儿有一个SQL啊, 这儿还有一个, 又来一个......”


MySQL刚开始非常高兴,满心欢喜地去执行,可是他很快就发现事情不对, 执行完这些SQL,在数据库中也查不到数据。他不满地对Tomcat说:“兄弟,你这是在折腾我吗? 你看看你这个SQL中where ID = xxxx, 这些ID在数据库都不存在嘛。”


Tomcat头也不抬:“又来一个SQL, 还有一个......”


让我比较佩服的是, MySQL还是比较职业的,尽管有怨气,他还是不折不扣地执行,很快他就累到了。


整个系统慢如蜗牛,连正常的请求也处理不了。


张大胖赶紧介入,经过一番调查,他发现很多请求故意去查询那些一定不存在的数据,缓存中肯定没有,于是请求一定会发到MySQL去执行,在流量大时,MySQL就挂掉了。


换句话说:在黑客的精心算计之下,我这个缓存成了摆设,缓存被穿透了!



张大胖把此事定性为黑客攻击。


缓存空值


这一次,MySQL终于意识到了我的价值,他出了一个主意:“Redis同学,你把那些不存在的key和对应的空值也缓存下来不就行了?下次访问,就直接返回一个null给这些黑客,别再来找我了。”


我一听就知道这是个馊主意:“这些key在你那里都不存在,还让我缓存,那不就是要浪费我的空间吗? 张大胖给我分配的空间是有限的啊。”


“你不是可以设定数据的有效期嘛,比如过3分钟就过期,删除它,空间不就腾出来了。”


“那在这三分钟内,如果这个key对应的数据真的被加入到了你MySQL当中,那岂不就不一致了?!” 我问道。


MySQL说道:“如果发生这种情况,就可以想办法清除掉缓存中的数据,只是程序逻辑就变得复杂了......”


“退一步来说,假设我缓存了他们,那黑客完全可以换一些新的key来攻击啊!缓存中还是没有,还得去你那里查,这个办法不妥!”  我下了结论。


布隆过滤器


MySQL说:“如果能事先得知这个key是不是在数据库存在就好了,可是想知道是否存在,那就得把所有的key都放到缓存中,Redis,你能受得了吗?”


我当然受不了。


Tomcat眼前一亮:“你们听说过布隆过滤器没有?”


我说:“当然知道了,这是个神奇的数据结构,只需要极少的空间就可以判断一个元素是不是在一个集合之内,这正好是我们所需要的场景啊:判断key是否存在。”


(码农翻身注:布隆过滤器大家可以参考相关资料,这里不再展开。)


Tomcat说:“对,比如我们可以把所有的用户ID建立一个布隆过滤器,这样当那些黑客的请求过来以后,先用这个过滤器拦截一下,如果黑客要访问的用户ID不在这个过滤器中,我们就直接把他踢出去了。”


MySQL也是经验丰富:“可是这个Bloom Filter有误报啊,即使某个用户ID不在集合中,他也可能报告说在集合中。这个时候Tomcat就认为这是一个合法的用户ID,就去Redis中查,不存在,然后到我这里查,还是不存在。”


我说:“哎呀,一定的误报也是允许的,没有完美的事情,总要付出代价不是?”


大家都表示同意。


数据失效


黑客的攻击的威胁解除了,日子又恢复了平静,MySQL意识到了我的价值,也不再唠唠叨叨了。


我这个缓存的容量是有限的,不可能无限制地增加,所以张大胖添加到缓存的数据有一个有效期,过了有效期,我就会把他删除,腾出空间,让别的数据使用。


如果是普通的缓存数据失效,那就罢了,大不了从数据库中再去一次就是了。


可是这一次,有个超级热门的数据失效了,Tomcat组成的集群中有无数的线程都问我要数据,当我告诉他们这个数据已经失效以后,他们扭头便转向MySQL,疯狂地发出SQL语句,问MySQL要数据。


MySQL傻眼了,这么多的线程,每个要发出的SQL都是相同的,可是又不得不执行。


MySQL又一次累倒了,我想他再次体会到了我的重要性。


他对Tomcat说道:“兄弟,给我发这么多的一模一样的SQL,你想累死我啊! 你就不能控制一下?只让一个线程发查询过来,让其他的等待一下? 那个线程取到数据以后,其他线程就可以从缓存取了!”


Tomcat觉得很有道理,可是现在系统中有多个Tomcat,每个都是平等的,怎么去选出那个唯一的线程呢?


如果是在同一个JVM中还好办,轻轻松松用一把进程内的锁搞定, 可是这分布式的Tomcat,每个都是一个JVM,每个都是一个进程, 怎么搞?


我说:“这很简单,我Redis这里可以提供一个分布式的锁,谁获得了这把锁,谁就可以访问数据库。”


MySQL佩服地说:“老弟真是不错,我服了你了,以后你一定要尽可能的把流量都给挡住,别往我这里发了,实在是太可怕了!”


Tomcat补充到:“是啊,这Redis缓存太重要了!”


突然间他注意到了我还只有一台机器: “你现在怎么还是单台机器? 一个实例? 万一挂了怎么办? 一定得像我一样,搞集群,提高可用性啊!”


MySQL说:“啊? 这多吓人,从今天开始,我将时时刻刻为你祈祷,上帝保佑,你千万别挂掉。”


与此同时,张大胖开始着手Redis集群了......


相关阅读:


小白科普:分布式和集群

负载均衡的原理

后端风云

MySQL:缓存是什么东西?!


(完)

码农翻身,用故事讲解技术本质, 更多精彩文章,请移步《码农翻身三年文章精华



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/R8lv2KeOPl
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/26009
 
523 次点击