使用Lua+Redis+OpenResty实现电商首页并发优化
Posted 恒哥~Bingo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Lua+Redis+OpenResty实现电商首页并发优化相关的知识,希望对你有一定的参考价值。
案例背景
电商首页通常都有广告轮播图,轮播图数据一般需要通过后台接口获得,当并发量较大时会给服务器带来压力。
一般的解决方案是将轮播图数据缓存到Redis中,这样就能减少对数据库的访问。
我们访问Redis也需要使用Java,Java项目部署在Tomcat中,Tomcat服务器也会面对并发量大的压力。
nginx服务器的并发性能要远远高于Tomcat,在Nginx中使用Lua脚本就能实现mysql和Redis的读写,绕过Tomcat,大大提高首页的并发性能。
案例需要使用OpenResty,参考:https://blog.csdn.net/u013343114/article/details/123991729
开发步骤
分为两大步骤:
1、缓存预热
2、缓存读取
缓存预热
使用Lua读取MySQL中的轮播图数据,保存到Redis中
ad_update.lua
-- 获得uri中的sid参数值
local uri_args = ngx.req.get_uri_args()
local sid = uri_args["sid"]
-- 连接mysql
local mysql = require "resty.mysql"
local db = mysql:new()
db:set_timeout(1000)
local ok, err = db:connect
host = "127.0.0.1",
port = 3306,
database = "edu_ad",
user = "root",
password = "123456",
charset = "utf8"
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected to mysql.")
-- 按区域编号查询轮播图表
local res, err = db:query("select * from promotion_ad where space_id="..sid)
if not res then
ngx.say("bad result: ", err)
return
end
db:close()
-- 结果转换为json
local cjson = require "cjson"
ngx.say("res->",cjson.encode(res))
-- 连接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(2000)
local ok,err = red:connect("127.0.0.1",6379)
if not ok then
ngx.say("connect error: ", err)
return
end
-- 保存到reids
red:set("ad_space_"..sid,cjson.encode(res))
red:close()
ngx.say("updated redis")
将ad_update.lua保存到openresty/nginx/conf/lua目录下
配置nginx.conf
server
listen 8080;
default_type 'applicaiton/json;charset=utf8';
charset utf-8;
location /ad_update
default_type text/html;
content_by_lua_file conf/lua/ad_update.lua;
访问测试
缓存读取
分为两级缓存,一级缓存是nginx内部缓存,二级是redis缓存,先读取内部缓存,如果没有再读取redis缓存
ad_load.lua
-- 获得sid参数
local uri_args = ngx.req.get_uri_args()
local sid = uri_args["sid"]
-- 读取内部缓存
local cache = ngx.shared.dis_cache:get('ad_space_'..sid)
if cache == nil then
-- 内部缓存没有读取redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(2000)
local ok, err = red:connect("127.0.0.1", 6379)
local res = red:get('ad_space:'..sid)
ngx.say(res)
red:close()
-- 保存到内部缓存
ngx.shared.dis_cache:set('ad_space_'..sid, res, 10*60);
else
ngx.say(cache)
end
配置nginx.conf
server
listen 8080;
default_type 'applicaiton/json;charset=utf8';
charset utf-8;
location /ad_update
default_type text/html;
content_by_lua_file conf/lua/ad_update.lua;
location /ad_load
default_type text/html;
content_by_lua_file conf/lua/ad_load.lua;
在http模块加内部缓存配置:
lua_shared_dict dis_cache 5m;
访问测试
首页
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>泡泡教育</title>
<link rel="stylesheet" href="css/index.css">
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<!--广告-->
<div style=" width:1200px; margin:0px auto; margin-top:20px;">
<el-carousel indicator-position="outside">
<el-carousel-item v-for="(item , index) in adList" :key="index">
<a :href="item.link">
<img :src="item.img" style='width: 100%;height: 100%;object-fit: cover;'/>
</a>
</el-carousel-item>
</el-carousel>
</div>
</div>
<script>
new Vue(
el:"#app",
name: "Index",
data()
return
adList: []
;
,
created()
this.getAdList();
,
methods:
// 获取顶部轮播广告
getAdList()
return axios
.get("http://192.168.7.188:8080/ad_load?sid=1")
.then((result) =>
console.log(result);
this.adList = result.data;
).catch( (error)=>
this.$message.error("获取轮播广告失败!");
);
);
</script>
</body>
</html>
将网部署到nginx的html目录中,配置首页
location /
default_type text/html;
root html/edu_learn_web;
index index.html;
测试
以上是关于使用Lua+Redis+OpenResty实现电商首页并发优化的主要内容,如果未能解决你的问题,请参考以下文章
使用Lua+Redis+OpenResty实现电商首页并发优化