OpenResty+lua+redis広告キャッシュを実現


OpenResty+lua+redis広告キャッシュを実現
一、需要
ngx_openrestyはNGINXベースのluaプログラマブルモジュールで、性能の面で優れた性能を持っており、redisと協力して2級キャッシュ効果を行い、nginxは1級ローカルキャッシュを開く.
実験データベースsql
/*
 Navicat Premium Data Transfer

 Source Server         :   mysql
 Source Server Type    : MySQL
 Source Server Version : 50728
 Source Host           : localhost:3306
 Source Schema         : demo

 Target Server Type    : MySQL
 Target Server Version : 50728
 File Encoding         : 65001

 Date: 25/05/2020 10:58:31
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_ad
-- ----------------------------
DROP TABLE IF EXISTS `tb_ad`;
CREATE TABLE `tb_ad`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '    ',
  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'URL',
  `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '0:    1:  ',
  `position` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '    ',
  `image` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '    ',
  `start_time` datetime(0) NULL DEFAULT NULL COMMENT '    ',
  `end_time` datetime(0) NULL DEFAULT NULL COMMENT '    ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_ad
-- ----------------------------
INSERT INTO `tb_ad` VALUES (1, 'https://www.baidu.com/', '1', 'web_index_lb', 'https://kins.oss-cn-shenzhen.aliyuncs.com/yhzb/2020-03-11/ca21b3b17d6f4757b991dd86b8cef3fa-VIP-680.jpeg', '2020-05-22 10:58:08', '2021-06-01 10:58:14');

SET FOREIGN_KEY_CHECKS = 1;

二、一二級キャッシュの実現
クエリmysqlに格納されているすべての広告はjson文字列に変換され、redisに格納されて2次キャッシュとして使用され、本格的な最初のクエリがキャッシュを1次ローカルキャッシュに追加します.広告が変更されると要求が必要になり、ウォームアップインタフェースを要求する必要があります.
nginx.confファイル構成
#user  nobody;
user root root;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    #  redis     
    lua_shared_dict dis_cache 5m;  #      
    
    server {
        listen       80;
        server_name  localhost;
        charset utf-8;
        #access_log  logs/host.access.log  main;
        #          
        location /ad_loading{
            content_by_lua_file /root/lua/ad_loading.lua;
        }
                location /ad_read {
                        content_by_lua_file /root/lua/ad_read.lua;
                }

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }        
    }
}

ad_loading.luaウォームアップスクリプト
ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
local uri_args = ngx.req.get_uri_args()
local position = uri_args["position"]

local db = mysql:new()
db:set_timeout(1000)  
local props = {  
    host = "127.0.0.1",  
    port = 3306,  
    database = "business",  
    user = "root",  
    password = "root"  
}

local res = db:connect(props)  
local select_sql = "select url,image from tb_ad where status ='1' and position='"..position.."' and start_time<= NOW() AND end_time>= NOW()"  
res = db:query(select_sql)  
db:close()  

local redis = require("resty.redis")
local red = redis:new()
red:set_timeout(2000)

local ip ="127.0.0.1"
local port = 6379
red:connect(ip,port)
--Redis Authentication
local result, err = red:auth("redis")
if not result then
    ngx.say("failed to authenticate: ", err)
    return
end

red:set("ad_"..position,cjson.encode(res))
red:close()

ngx.say("{flag:true}")

ad_read.lua読み取りスクリプト
--       
ngx.header.content_type="application/json;charset=utf8"
--        ID
local uri_args = ngx.req.get_uri_args();
local position = uri_args["position"];

--      
local cache_ngx = ngx.shared.dis_cache;
--  ID         
local adCache = cache_ngx:get('ad_cache_'..position);

if adCache == "" or adCache == nil then

    local redis = require("resty.redis");
    local red = redis:new()
    red:set_timeout(2000)
    local ok, err = red:connect("127.0.0.1", 6379)
    --Redis Authentication
    local result, err = red:auth("redis")
    if not result then
        ngx.say("failed to authenticate: ", err)
        return
    end
    local rescontent=red:get("ad_"..position)
    ngx.say(rescontent)
    red:close()
    -- redis          nginx    
    cache_ngx:set('ad_cache_'..position, rescontent, 10*60);
else
     --nginx              
     ngx.say(adCache)
end

三、方向を広げる
lua+nginxはゲートウェイとして限流、フロー制御、マルチレベルキャッシュとして使用することができ、メモリが小さくて使用性も非常に高く、luaモジュールと協力して深く拡張することができます.