(1)为何要用缓存集群node
(2)20万用户同时访问一个热点缓存redis
(3)基于流式计算的缓存热点自动发现数据库
(4)热点缓存自动加载为JVM本地缓存缓存
(5)限流熔断保护服务器
(6)总结网络
本文是笔者以前写过的一篇文章,之因此新瓶装旧酒,是想借着广大程序猿兄弟们的国民女神:志玲姐姐结婚这一热点话题,看看面对如此大的一个热点缓存,我们的攻城狮兄弟应该如何设计系统架构,才能抗住瞬间高峰的粉丝流量!架构
也但愿能借着这种热点话题,帮你们从新复习一下热点缓存架构设计相关的技术要点!并发
话很少说,进入正题!负载均衡
其实使用缓存集群的时候,最怕的就是热key、大value这两种状况,那啥叫热key大value呢?memcached
简单来讲,热key,就是你的缓存集群中的某个key瞬间被数万甚至十万的并发请求打爆。大value,就是你的某个key对应的value可能有GB级的大小,致使查询value的时候致使网络相关的故障问题。
咱们先来看看下面一幅图,假设你手头有个系统,他自己是集群部署的,而后后面有一套缓存集群,这个集群无论你用redis cluster,仍是memcached,或者是公司自研缓存集群,均可以。
那么,这套系统用缓存集群干什么呢?
很简单,在缓存里放一些平时不怎么变更的数据,而后用户在查询大量的平时不怎么变更的数据的时候,不就能够直接从缓存里走了吗?
缓存集群的并发能力是很强的,并且读缓存的性能是很高的。举个例子,假设你每秒有2万请求,可是其中90%都是读请求,那么每秒1.8万请求都是在读一些不太变化的数据,而不是写数据。
那此时你把这些数据都放在数据库里,而后每秒发送2万请求到数据库上读写数据,你以为合适吗?
固然不合适了,若是你要用数据库承载每秒2万请求的话,那么很差意思,你极可能就得搞分库分表 + 读写分离。
好比你得分3个主库,承载每秒2000的写入请求,而后每一个主库挂3个从库,一共9个从库承载每秒1.8万的读请求。
这样的话,你可能就须要一共是12台高配置的数据库服务器,这是很耗费钱的,成本很是高,很不合适。
你们看看下面的图,来体会下这种状况。
所以,咱们彻底能够把平时不太变化的数据放在缓存集群里,缓存集群能够采用2主2从,主节点用来写入缓存,从节点用来读缓存。
以缓存集群的性能,2个从节点彻底能够用来承载每秒1.8万的大量读请求,而后3个数据库主库就是承载每秒2000的写请求和少许其余读请求就OK了。
这样一来,你耗费的机器瞬间变成了4台缓存机器 + 3台数据库机器 = 7台机器,是否是比以前的12台机器减小了很大的资源开销?
没错,缓存其实在系统架构里是很是重要的组成部分。不少时候,对于那些不多变化可是大量高并发读的数据,经过缓存集群来抗高并发读,是很是合适的。
咱们看看下面的图,体会一下这个过程。
须要说明的是,这里全部的机器数量、并发请求量都是一个示例,你们主要是体会一下这个意思就好,其目的主要是给一些不太熟悉缓存相关技术的同窗一点背景性的阐述,让这些同窗可以理解在系统里用缓存集群承载读请求是什么意思。
好了,背景已经给你们解释清楚,如今就能够给你们说说今天重点要讨论的问题:热点缓存。
咱们来作一个假设,如今有10个缓存节点来抗大量的读请求。正常状况下,读请求应该是均匀的落在10个缓存节点上的,对吧!
这10个缓存节点,每秒承载1万请求是差很少的。
而后咱们再作一个假设,你一个节点承载2万请求是极限,因此通常你就限制一个节点正常承载1万请求就ok了,稍微留一点buffer出来。
好,所谓的热点缓存问题是什么意思呢?很简单,就是忽然由于莫名的缘由,出现大量的用户访问同一条缓存数据。
好比林志玲忽然宣布结婚,这时是否是会引起短期内每秒都数十万用户去查看这条热点新闻?
假设这条新闻就是一个缓存,对应一个缓存key,就存在一台缓存机器上,此时瞬时假设有20万请求奔向那一台机器上的一个key。
此时会如何?咱们看看下面的图,来体会一下这种绝望的感觉。
很明显了,咱们刚才假设的是一个缓存Slave节点最多每秒就是2万的请求,固然实际缓存单机承载5万~10万读请求也是可能的,这里就是一个假设。
结果每秒忽然奔过来20万请求到这台机器上,会怎么样?很简单,上面图里那台被20万请求指向的缓存机器会过分操劳而宕机的。
那么若是缓存集群开始出现机器的宕机,此时会如何?
此时读请求发现读不到数据,会从数据库里提取原始数据,而后放入剩余的其余缓存机器里去。可是接踵而来的每秒20万请求,会再次压垮其余的缓存机器。
以此类推,最终致使缓存集群全盘崩溃,引起系统总体宕机。
我们看看下面的图,再感觉一下这个恐怖的现场。
其实这里关键的一点,就是对于这种热点缓存,你的系统须要可以在热点缓存忽然发生的时候,直接发现他,而后瞬间立马实现毫秒级的自动负载均衡。
那么咱们就先来讲说,你如何自动发现热点缓存问题?
首先你要知道,通常出现缓存热点的时候,你的每秒并发确定是很高的,可能每秒都几十万甚至上百万的请求量过来,这都是有可能的。
因此,此时彻底能够基于大数据领域的流式计算技术来进行实时数据访问次数的统计,好比storm、spark streaming、flink。
一旦在实时数据访问次数统计的过程当中,好比发现一秒以内,某条数据忽然访问次数超过了1000,就直接立马把这条数据断定为是热点数据,能够将这个发现出来的热点数据写入好比zookeeper中。
固然,你的系统如何断定热点数据,能够根据本身的业务还有经验值来就能够了。
你们看看下面这张图,看看整个流程是如何进行的。
这里确定有人会问,那你的流式计算系统在进行数据访问次数统计的时候,会不会也存在说单台机器被请求每秒几十万次的问题呢?
答案是:否
由于流式计算技术,尤为是storm这种系统,他能够作到同一条数据的请求过来,先分散在不少机器里进行本地计算,最后再汇总局部计算结果到一台机器进行全局汇总。
因此几十万请求能够先分散在好比100台机器上,每台机器统计了这条数据的几千次请求。
而后100条局部计算好的结果汇总到一台机器作全局计算便可,因此基于流式计算技术来进行统计是不会有热点问题的。
咱们本身的系统能够对zookeeper指定的热点缓存对应的znode进行监听,若是有变化他立马就能够感知到了。
此时系统层就能够立马把相关的缓存数据从数据库加载出来,而后直接放在本身系统内部的本地缓存里便可。
这个本地缓存,你用ehcache、hashmap,其实均可以,一切看本身的业务需求。咱们这里主要说的就是将缓存集群里的集中式缓存,直接变成每一个系统本身本地实现缓存便可,每一个系统本地是没法缓存过多数据的。
由于通常这种普通系统单实例部署机器可能就一个4核8G的机器,留给本地缓存的空间是不多的,因此用来放这种热点数据的本地缓存是最合适的,刚恰好。
假设你的系统层集群部署了100台机器,那么好了,此时你100台机器瞬间在本地都会有一份热点缓存的副本。
而后接下来对热点缓存的读操做,直接系统本地缓存读出来就给返回了,不用再走缓存集群了。
这样的话,也不可能容许每秒20万的读请求到达缓存机器的一台机器上读一个热点缓存了,而是变成100台机器每台机器承载数千请求,那么那数千请求就直接从机器本地缓存返回数据了,这是没有问题的。
咱们再来画一幅图,一块儿来看看这个过程:
除此以外,在每一个系统内部,其实还应该专门加一个对热点数据访问的限流熔断保护措施。
每一个系统实例内部,均可以加一个熔断保护机制,假设缓存集群最多每秒承载4万读请求,那么你一共有100个系统实例。
你本身就该限制好,每一个系统实例每秒最多请求缓存集群读操做不超过400次,一超过就能够熔断掉,不让请求缓存集群,直接返回一个空白信息,而后用户稍后会自行再次从新刷新页面之类的。
经过系统层本身直接加限流熔断保护措施,能够很好的保护后面的缓存集群、数据库集群之类的不要被打死。
再来一幅图,一块儿来看看:
(6)本文总结
具体要不要在系统里实现这种复杂的缓存热点优化架构呢?这个还要看大家本身的系统有没有这种场景了。
若是你的系统有热点缓存问题,那么就要实现相似本文的复杂热点缓存支撑架构。可是若是没有的话,那么也别过分设计,其实你的系统可能根本不须要这么复杂的架构。
若是是后者,那么大伙儿就权当看看本文,了解一下对应的架构思想好了
最后,向端午节前夕,还奋战在一线的广大攻城狮兄弟们,大家是最可爱的人 ^_^
END
我的公众号:石杉的架构笔记(ID:shishan100)
欢迎长按下图关注公众号:石杉的架构笔记!
公众号后台回复资料,获取做者独家秘制学习资料
石杉的架构笔记,BAT架构经验倾囊相授