畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

好好学习,天天向上

本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航

首页广告介绍

流程

在商城的首页,我们会看到很多广告,而很多时候这些广告内容都是固定的,所以每次访问MySQL获取广告内容效率是非常低的,比较好的做法就是用Redis和OpenResty做多级缓存。如果缓存中有数据就访问缓存,没有的话再去MySQL中获取,可以大大提高性能。
畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

表结构

广告的数据是存放在changgou-content数据库中(我的这份资料里面没有这个数据库,我就自己创建了一个)。里面有两张表,一张是tb_content_catrgory(广告分类表),根据页面的不同位置,广告有不同的分类,比如首页轮播,猜你喜欢等;另一张是tb_content(广告表),这张表里存放了广告的数据。
畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

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、Canal实现广告缓存与同步

基本语法

参考菜鸟教程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的虚拟机,如果出现了欢迎界面就说明安装成功了。
畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

配置

虽然现在已经可以访问到OpenResty了,但是为了能够直接加载到root目录下的lua脚本,还需要配置一下。

cd /usr/local/openresty/nginx/conf			# 切换到openresty安装目录下的nginx目录中的conf目录中
vi nginx.conf							  #编辑nginx的配置文件

畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步

广告缓存的载入与读取

本节的任务就是: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、OpenResty、Canal实现广告缓存与同步

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中添加图中内容

上一篇:「从零单排canal 06」 instance模块源码解析


下一篇:canal同步mysql数据至es5.5.0