目录
前言
项目地址:eshop-study
切换到相应分支:
瞬间缓存热点问题
-
上一章我们解决的缓存冷启动问题: 热数据 -> 热数据的统计 -> redis中缓存的预热 -> 避免新系统刚上线,或者是redis崩溃数据丢失后重启,redis中没有数据,redis冷启动 -> 大量流量直接到数据库; redis启动前,必须确保其中是有部分热数据的缓存的
-
本章我们要解决
瞬间的缓存热点
基于nginx+lua+storm的热点缓存的流量分发策略自动降级解决方案
方案思路
storm实时计算热点
- 在storm中,实时的计算出瞬间出现的热点
- 有很多种算法,简单的算法,某个
storm task
,上面算出了1万个商品的访问次数,商品id和访问次数存到``LRUMap - 频率高一些,每隔5秒,去遍历一次
LRUMap
,将其中的访问次数进行排序,统计出往后排的95%的商品访问次数的平均值 - 比如商品id列表: [1000,999,888,777,666,50,60,80,100,120],95%的商品即1000后面的9个商品id,访问次数的平均值是100,然后,从最前面开始,往后遍历,去找有没有瞬间出现的热点数据,这里就只是判断第一个;
- 设定一个热点商品访问次数阈值,比如95%的平均值(100)的10倍,如果
LRUMap
中第一个商品id的访问次数超过这个值,我们就认为是瞬间出现的热点数据 - 当遍历,发现说第一个商品的访问次数,小于平均值的10倍,让该商品id热点消失,break循环
storm发送热点到nginx
storm
通过算法计算出热点商品id列表后,会直接发送http请求到nginx
上,nginx上用lua脚本
去处理这个请求- storm会将热点本身对应的
productId
,发送到流量分发nginx
上面去,放在本地缓存中; - storm会将热点对应的完整的
商品详情
缓存数据,发送到所有的应用nginx服务器
上去,直接放在本地缓存中
nginx的分发策略降级
流量分发nginx
,添加逻辑:每次访问一个商品详情页的时候,如果发现它是个热点,那么立即做流量分发策略的降级- 之前的普通商品请求
hash策略
:同一个productId的访问都同一台应用nginx服务器上,降级成对这个热点商品,流量分发采取负载均衡
发送到所有的后端应用nginx
服务器上去 - 瞬间将热点缓存数据的访问,从hash分发全部到一台nginx,变成了,负载均衡发送到多台nginx上去
- 避免说大量的流量全部集中到一台机器,50万的访问量到一台nginx,5台应用nginx,每台就可以承载10万的访问量
storm热点取消逻辑
-
storm还需要保存下来上次识别出来的
热点list
-
下次去识别的时候,这次的热点list跟上次的热点list做一下diff,看看可能有的商品已经不是热点了
-
热点的取消的逻辑,发送http请求到流量分发的nginx上去,取消掉对应的热点数据,从nginx本地缓存中,删除
实战
热点商品计算
- 在storm拓扑中加入热点缓存实时自动识别和感知的代码逻辑
- 在storm拓扑中加入nginx反向推送缓存热点与缓存数据的代码逻辑
- 在流量分发+后端应用双层nginx中加入接收热点缓存数据的接口
流量分发nginx
服务机器: [eshop-cache03: 192.168.0.108]
vi /usr/hello/hello.conf
location /hot {
default_type 'text/html';
# lua_code_cache off;
content_by_lua_file /usr/hello/lua/hot.lua;
}
vi /usr/hello/lua/hot.lua
local uri_args = ngx.req.get_uri_args()
local product_id = uri_args["productId"]
local cache_ngx = ngx.shared.my_cache
local hot_product_cache_key = "hot_product_"..product_id
-- 缓存1小时
cache_ngx:set(hot_product_cache_key, "true", 60 * 60)
- 重启nginx:
/usr/servers/nginx/sbin/nginx -s reload
服务应用nginx
服务机器: [eshop-cache01: 192.168.0.106]
、[eshop-cache02: 192.168.0.107]
- 同上面小节分发nginx
[eshop-cache03: 192.168.0.108]
的第一步; - 同上面小节分