本次阅读了有关架构优化的文章,文章一共分为了五个部分来介绍架构以及其如何优化的内容,并用一个实例来分析如何去优化架构。
一、为什么要用缓存集群
热点缓存在使用缓存集群的时候最害怕出现两个情况:热key和大value。
热key就是你的缓存集群中的某个key瞬间被数万甚至十万的并发请求打爆。
大value,就是你的某个key对应的value可能有GB级的大小,导致查询value的时候导致网络相关的故障问题。
简单的去理解,一个系统他的本身是集群部署的,然后有一套缓存集群,这个集群不论是用redis cluster还是memcached,或者是公司自主研发的缓存集群都可以。这些缓存集群放了一些平时不变动或者很少变动的数据,用户查询这些数据时可以直接从缓存里走。缓存集群的并发能力、读缓存性能都非常高。假设设每秒有2万请求,但是其中90%都是读请求,那么每秒1.8万请求都是在读一些不太变化的数据,而不是写数据。那此时数据都放在数据库里,然后每秒发送2万请求到数据库上读写数据,不太合适,如果你要用数据库承载每秒2万请求的话,你就得搞分库分表 + 读写分离。成本非常高,而且很不合适。所以,可以把不变动或者很少变动的数据放在缓存集群里,对于那些很少变化但是大量高并发读的数据,通过缓存集群实现高并发、读缓存,是非常合适的。
二、几十万用户同时访问一个热点缓存问题
假设,现在有10个缓存节点来抗大量的读请求。正常情况下,读请求应该是均匀的落在10个缓存节点上的。这10个缓存节点,每秒承载1万请求。再做一个假设,一个节点承载2万请求是极限,所以限制一个节点正常承载1万请求,留一些buffer出来。
热点缓存的意识就是:突然出现大量的用户同时访问同一条数据。
举个例子:微博热搜(很短时间内几百万甚至几亿的访问量)
这个热搜就是一个缓存,对应的就是一个缓存key,在一个缓存机器上瞬间有几十万的请求访问这台机器上的这个key。此时,每秒突然奔过来一些几十万请求到这台机器上,那台被几十万请求指向的缓存机器会过度操劳而宕机。如果缓存集群开始出现机器的宕机,读请求发现读不到数据,会从数据库里提取原始数据,然后放入剩余的其他缓存机器里去。但是接踵而来的每秒几十万请求,会再次压垮其他的缓存机器。以此类推,最终导致缓存集群全盘崩溃,引发系统整体宕机。
三、基于流式计算技术的缓存热点自动发现
这里关键的一点,就是对于这种热点缓存,系统需要能够在热点缓存突然发生的时候,直接发现他,然后瞬间立马实现毫秒级的自动负载均衡。
如何自动发现热点缓存问题?
首先要知道,一般出现缓存热点的时候,你的每秒并发肯定是很高的,可能每秒都几十万甚至上百万的请求量过来,这都是有可能的。所以,可以用基于大数据领域的流式计算技术来进行实时数据访问次数的统计,比如storm、spark streaming、flink。在实时数据访问次数统计的过程中,比如发现一秒之内,突然某条数据访问次数超过了1000,就立马把这条数据判定为是热点数据,将这个发现出来的热点数据写入比如zookeeper中。
四、热点缓存自动加载为JVM本地缓存
系统可以对zookeeper指定的热点缓存对应的znode进行监听,如果有变化他立马就可以感知到了。此时系统层就可以立马把相关的缓存数据从数据库加载出来,然后直接放在自己系统内部的本地缓存里即可。将缓存集群里的集中式缓存,直接变成每个系统自己本地实现缓存即可,每个系统自己本地是无法缓存过多数据的。然后接下来对热点缓存的读操作,直接系统本地缓存读出来就给返回,不用再走缓存集群。这样的话,也不可能允许每秒20万的读请求到达缓存机器的一台机器上读一个热点缓存了,而是变成100台机器每台机器承载数千请求,那么那数千请求就直接从机器本地缓存返回数据了,这是没有问题的。
五、限流熔断保护
每个系统实例内部,都可以加一个熔断保护机制,假设缓存集群最多每秒承载4万读请求,那么你一共有100个系统实例。每个系统实例每秒最多请求缓存集群读操作不超过400次,一超过就可以熔断掉,不让请求缓存集群,直接返回一个稍等刷新页面等等。通过系统层自己直接加限流熔断保护措施,可以很好的保护后面的缓存集群、数据库集群等。
总结:
要根据实际系统去分析要不要使用热点缓存架构优化。