- 热点数据:经常查询或者需要更新的数据
- 冷门数据:不经常修改或者不经常查询的数据
对于冷热数据我们有不同的处理,我们知道库存是随着用户下单而变化的,这个是需要实时的,我们姑且成为热点数据,而商品名称却不是。
对于商品本身的数据我们在获取这块的处理会不同,对于库存和价格这种热点数据我们会在页面加载完成之后进行异步加载,而对于冷门数据,我们会使用nginx将数据局与html页面一起进行缓存。
对于商品而言,我们对于活动的商品信息也会在nginx中开辟出一个缓存,这样在用户访问活动商品的时候,就不用再去请求数据库,浪费更多的网络资源与时间。而冷商品仅仅交给数据库进行处理就 OK了,不过对于不会经常更新的数据还是会缓存一份数据到Redis中的。
代码展示:
php完成商品详情数据api接口
//热点商品的Redis key
protected $productKey;
//商品的计数器 ,访问量 缓存时间7天 超过1w就进行Redis缓存
protected $productCountKey;
//商品计数,访问量缓存七天,七天超过1w就进行redis缓存
public function productItems(Request $request){
//获取商品id
if($product_id = $request->input('product_id')){
$this->productKey = "Lmrs::product::info::".$product_id;
$this->productCountKey = "Lmrs::product::count::".$product_id;
//先判断redis中是否有相关数据,没有则去数据库中(es)中查询
$productInfo = Redis::get($this->productKey);
if ($productInfo == null or $productInfo == false){
#此处es暂代数据库
$builder = (new ElasticsearchService('products'))->IsStatus()->productIdSearch($product_id);
$restful =app('es')->search($builder->getParams());
$restful = collect($restful["hits"]["hits"])->pluck('_source')->all();
//缓存7天,七天累计计数
$exists = Redis::set($this->productCountKey,1,"NX","EX",100800);
//七天访问量超过一万的数据存入缓存
if(Redis::incr($this->productCountKey) >= 10000){
Redis::set($this->productKey,serialize($restful),"EX",100800);
}
return response()->json($restful[0]);
}
return response()->json(unserialize($productInfo)[0]);
}else{
return response()->json([
"restful" => false,
"data" => "参数异常"
]);
}
}
nginx+lua获取调用这个api
在服务器的/docker/www/lua目录下创建一个lua脚本(products.lua),写下如下代码:
local uri_args = ngx.req.get_uri_args() --获取url中传递的参数,如商品id
local productId = uri_args["product_id"]
local cache_ngx = ngx.shared.productCache --调用nginx中配置的productCache缓存
local cjson = require("cjson") --引入lua的json依赖
local productCacheKey = "lmrs::product::info::"..productId --通过我们获取的商品id,拼接一个nginx缓存的key
local productCache = cache_ngx:get(productCacheKey) --在nginx缓存中查询这个key的数据
if productCache == "" or productCache == nil then --判断是否查询到数据
local http = require("resty.http") --引入lua的http依赖
local httpc = http.new()
local url = "http://172.17.0.6/api/productInfo?product_id="..productId --请求的地址(与laravel中定义的路由对应)
local resp,err = httpc:request_uri(url,{
method = "POST", --什么方式请求
body = body,
headers = { --请求头
["Content-Type"] = "application/x-www-form-urlencoded",
}
})
productCache = resp.body --取得数据主体
cache_ngx:set(productCacheKey,productCache,10 * 60) --存入nginx缓存中
end
local productCacheJson = cjson.decode(productCache) --解析json的数据为table
local productInfo = { --制定需要发返回的数据
product_id = productId,
product_name = productCacheJson["name"],
product_long_name = productCacheJson["long_name"],
product_sold_count = productCacheJson["sold_count"],
product_review_count = productCacheJson["review_count"]
}
local template = require("resty.template") --引入lua的前端模板渲染依赖
template.render("template.html",productInfo) --渲染模板
在openresty容器中移入相关依赖:
docker exec -it openresty bash
cd /usr/local/openresty/lualib/resty
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_connect.lua
如果拒绝访问在在hosts加上
199.232.4.133 raw.githubusercontent.com
退出容器后,重启Openresty
docker restart openresty
nginx中引入lua脚本进行测试
openresty中的nginx配置如下:
#定义共享空间
lua_shared_dict dis_cache 10m;
lua_shared_dict productCache 200m;
lua_package_path "/usr/local/openresty/lualib/?.lua;";
lua_package_cpath "/usr/local/openresty/lualib/?.so;";
server
{
listen 90;
listen [::]:90;
server_name localhost;
root /docker/www/webserver;
index index.html;
#html模板存放位置
set $template_root "/docker/www/products";
location /lmrs_home_index {
content_by_lua_file /docker/www/lua/lmrs_home_index.lua;
}
location /productinfo{
default_type 'text/html';
content_by_lua_file /docker/www/lua/products.lua;
}
}
nginx容器的配置如下:(注意这里的nginx不是Openresty中的nginx,而是我们通过docker安装的nginx容器配置)
proxy_cache_path /cache/productinfo levels=1:2 keys_zone=productinfo:200m max_size=5g inactive=60m use_temp_path=off;
upstream openresty{
server 172.17.0.5:90 weight=5 max_fails=3 fail_timeout=30s;
}
server {
···
···
···
location /productinfo {
proxy_cache productinfo;
proxy_cache_valid 200 206 304 302 1d;
proxy_cache_key $request_uri;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://openresty;
}
···
···
···
}
前端模板配置
lua的template依赖是需要我们配置好html的模板的,在这个模板我们会配置好需要缓存起来的冷数据,比如商品名称这些。使用ajax去异步加载价格和库存。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{* product_name *}</title>
<script type="text/javascript" src="http://192.168.35.137:90/static/js/jquery_4.js"></script>
</head>
<body>
商品名称:{* product_name *}
销量:{* product_sold_count *}
评价:{* product_review_count *}
<input id="product_id" type="hidden" value="{* product_id *}">
<script type="text/javascript">
var product_id = document.getElementById("product_id").value;
$.ajax({
type: "post",
url: "http://192.168.35.137/api/productInfo",
data:{"product_id":product_id},
success: function(data) {
var html = "<p>";
html += "价格:"+data.price;
$("body").append(html);
}
});
</script>
</body>
</html>
效果展示