1. 程式人生 > 實用技巧 >暢購商城(四):Lua、OpenResty、Canal實現廣告快取與同步

暢購商城(四):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中新增圖中內容