涉及图片部分访问这个地址:http://note.youdao.com/noteshare?id=55c8fe08359e502ca6434b63d4b5dc0d
假设最近一段时间内有10万个请求过来,其中1万次请求访问商品1,2万次请求访问商品2,3万次请求访问商品3,其他商品被访问次数均匀。请实时统计热点数据展示出来。
说下主要的解决步骤:
1.分发层nginx将所有的请求hash分发到对应的应用层nginx,防止第一次请求落到了应用层nginx1,访问数据库,加了点缓存,第二次请求落到了nginx2,缓存没有,照样访问数据库了,因此,需要保证productid=1的商品请求只会落到对应的应用层nginx上处理。
2.需要三级缓存架构,应用层nginx本地缓存+ 缓存生产服务(redis缓存+enchache缓存)
3.数据库修改后,需要发送一条数据修改消息给队列,缓存生产服务监听到这个消息,会自主的更新缓存
4.用户请求到达应用层nginx后,即使缓存被命中了,也需要统计出来用户的这次访问请求吧,因此,每请求一次就需要用nginx+lua向kafka发送一条自定义的消息,用于后续请求处理。
5.strom从kafka队列消费消息,并统计出来每个商品的访问次数,并统计出来前5名的商品productid,将productidlist
的信息分段存储在zookeeper中。
6.在做热储备的时候,需要从zookeeper中获取分布式锁,读取节点信息,写入到缓存生产服务中去。
1.首先是请求分发,需要nginx+lua脚本,分发nginx在收到请求的时候,计算出hash值,发送一个http请求到应用层上去处理。
这句话(local uri_args = ngx.req.get_uri_args())的意思是:
拿到url请求地址的参数
local uri_args = ngx.req.get_uri_args()
local productId = uri_args["productId"]
定义我们需要分发的应用层服务器ip地址,对商品id进行取模,得到选用的服务器的ip地址,字符串拼接使用..
注意:2不是写死的,代表的是备用服务器ip地址的个数,hash%2不是0就是1,那么加1得到的就是1,2,lua脚本中的local host不同于数组下标是从0开始的
local host = {"192.168.31.19", "192.168.31.187"}
local hash = ngx.crc32_long(productId)
local index = (hash % 2) + 1
local backend = "http://"..host[index]
对于method的处理,requestPath是不带参数也不带host的请求地址,/hello,请求拼接就是requestPath+参数