暢購商城(四):Lua、OpenResty、Canal實現廣告快取與同步
好好學習,天天向上
本文已收錄至我的Github倉庫DayDayUP:github.com/RobodLee/DayDayUP,歡迎Star,更多文章請前往:目錄導航
首頁廣告介紹
流程
在商城的首頁,我們會看到很多廣告,而很多時候這些廣告內容都是固定的,所以每次訪問MySQL獲取廣告內容效率是非常低的,比較好的做法就是用Redis和OpenResty做多級快取。如果快取中有資料就訪問快取,沒有的話再去MySQL中獲取,可以大大提高效能。
表結構
廣告的資料是存放在changgou-content資料庫中(我的這份資料裡面沒有這個資料庫,我就自己建立了一個)。裡面有兩張表,一張是tb_content_catrgory(廣告分類表),根據頁面的不同位置,廣告有不同的分類,比如首頁輪播,猜你喜歡等;另一張是tb_content(廣告表),這張表裡存放了廣告的資料。
CREATE TABLE `tb_content_category` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '類目ID', `name` VARCHAR(50) DEFAULT NULL COMMENT '分類名稱', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='內容分類'; INSERT INTO `tb_content_category` VALUES (1, '首頁輪播廣告'); INSERT INTO `tb_content_category` VALUES (2, '今日推薦A'); INSERT INTO `tb_content_category` VALUES (3, '活動專區'); INSERT INTO `tb_content_category` VALUES (4, '猜你喜歡'); CREATE TABLE `tb_content` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `category_id` BIGINT(20) NOT NULL COMMENT '內容類目ID', `title` VARCHAR(200) DEFAULT NULL COMMENT '內容標題', `url` VARCHAR(500) DEFAULT NULL COMMENT '連結', `pic` VARCHAR(300) DEFAULT NULL COMMENT '圖片絕對路徑', `status` VARCHAR(1) DEFAULT NULL COMMENT '狀態,0無效,1有效', `sort_order` INT(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`), KEY `category_id` (`category_id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; INSERT INTO `tb_content` VALUES (1, 1, '微信廣告', 'https://blog.csdn.net/weixin_43461520', 'https://gitee.com/RobodLee/image_store/raw/master/%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7.png', '1', 1);
Lua
簡介
Lua是一種輕量小巧的指令碼語言,用標準C語言編寫並以原始碼形式開放, 其設計目的是為了嵌入應用程式中,從而為應用程式提供靈活的擴充套件和定製功能。
安裝
cd /usr/local/server # 切換到想要下載的目錄,隨意 curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz # 下載Lua5.3.5 tar zxf lua-5.3.5.tar.gz # 解壓 cd lua-5.3.5 # 切換到解壓後的目錄 make linux test # 安裝 ------------------------------------------------------------------------------------- [root@localhost lua-5.3.5]# lua # 輸入lua,出現下面一行說明安裝成功 Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
程式設計方式
Lua有互動式程式設計和指令碼式程式設計兩種方式。
互動式程式設計
互動式程式設計是輸入lua命令後進入到lua控制檯,然後輸入lua命令來執行。
[root@localhost lua-5.3.5]# lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print("Hello World!")
Hello World!
>
指令碼式程式設計
指令碼式程式設計就是建立一個.lua檔案,然後輸入命令“lua filename.lua”來執行。
基本語法
參考菜鳥教程Lua
OpenResty
簡介
OpenResty 是一個強大的 Web 應用伺服器,Web 開發人員可以使用 Lua 指令碼語言調動 Nginx 支援的各種 C 以及 Lua 模組,更主要的是在效能方面,OpenResty可以快速構造出足以勝任 10K 以上併發連線響應的超高效能 Web 應用系統。就是封裝了Nginx,並且集成了Lua指令碼,開發人員只需要簡單地使用提供的模組就可以實現相關的邏輯,而不再像之前,還需要在nginx中自己編寫lua的指令碼,再進行呼叫了。
安裝
yum install yum-utils # 安裝yum-utils,為了使用下面一行的命令
# 新增openresty的倉庫,不配置這一行安裝不了
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
yum install openresty # 安裝openresty,介面會有提示,一路按y就可以了
安裝完成之後,不要忘了啟動
service openresty start
啟動完成之後,用瀏覽器訪問安裝了openresty的虛擬機器,如果出現了歡迎介面就說明安裝成功了。
配置
雖然現在已經可以訪問到OpenResty了,但是為了能夠直接載入到root目錄下的lua指令碼,還需要配置一下。
cd /usr/local/openresty/nginx/conf # 切換到openresty安裝目錄下的nginx目錄中的conf目錄中
vi nginx.conf #編輯nginx的配置檔案
廣告快取的載入與讀取
本節的任務就是:Nginx攔截http://192.168.31.200/read_content?id=1,執行Lua指令碼,先從Nginx快取中載入,沒有的話就從Redis中載入,再沒有的話就從MySQL中載入,然後MySQL——>Redis——>Nginx——>瀏覽器。
定義Nginx快取模組
cd /usr/local/openresty/nginx/conf # nginx的配置目錄
vi nginx.conf # 編輯nginx的配置檔案
在http裡面配置Nginx的快取模組:
Lua指令碼
然後,準備好lua指令碼,在root/lua目錄下建立一個read_content.lua檔案,填入以下內容:
ngx.header.content_type="application/json;charset=utf8"
local uri_args = ngx.req.get_uri_args(); -- 獲取uri中的所有引數
local id = uri_args["id"]; -- 獲取名為id的引數
--獲取本地快取
local cache_ngx = ngx.shared.dis_cache; -- 載入Nginx快取模組,需要先定義
--根據ID 獲取本地快取資料
local contentCache = cache_ngx:get('content_cache_'..id);
--[[
Nginx中有快取就輸出快取,沒有的話就從Redis中載入
--]]
if contentCache == "" or contentCache == nil then
local redis = require("resty.redis"); -- 依賴Redis模組
local red = redis:new() -- 建立Redis物件
red:set_timeout(2000) -- 超時
red:connect("192.168.31.200", 6379) -- 連線Redis
local rescontent=red:get("content_"..id); -- 從Redis中讀資料
-- Redis中沒有就從MySQL中載入
if ngx.null == rescontent then
local cjson = require("cjson"); -- 依賴json模組
local mysql = require("resty.mysql"); -- 依賴mysql模組
local db = mysql:new(); -- 建立mysql物件
db:set_timeout(2000) -- 設定過期時間
-- mysql的引數資訊
local props = {
host = "192.168.31.200",
port = 3306,
database = "changgou_content",
user = "root",
password = "root"
}
local res = db:connect(props); -- 連線mysql
local select_sql = "select url,pic from tb_content where status ='1' and category_id="..id.." order by sort_order";
res = db:query(select_sql); --執行sql
local responsejson = cjson.encode(res); -- 將mysql返回的資料轉換成json
red:set("content_"..id,responsejson); -- 存到Redis中
ngx.say(responsejson); -- 輸出
db:close() -- 關閉mysql連線
else
cache_ngx:set('content_cache_'..id, rescontent, 10*60); -- 把Redis中的資料寫到Nginx快取中,設定過期時間
ngx.say(rescontent) -- 輸出
end
red:close() -- 關閉Redis連線
else
ngx.say(contentCache) -- 輸出
end
配置Nginx
現在需要配置一下nginx,讓它能夠執行該指令碼。編輯上面提到的nginx.conf檔案,在http.server中新增圖中內容