nginx+lua+redis实现缓存总结

场景:
对于一个网站首页,访问量一般是巨大的,如果每次用户请求访问都去请求服务器,服务器再查询数据库,当访问量巨大的时候,无疑对服务器和数据库产生巨大的压力,利用缓存机制就能有效减轻对数据库请求的压力

1.分析步骤

步骤一:缓存lua脚本实现缓存预热(将mysql里的数据查询出来存入redis)
nginx+lua+redis实现缓存总结_第1张图片
步骤二:编写lua脚本实现二级缓存读取
nginx+lua+redis实现缓存总结_第2张图片

2.OpenResty介绍

OpenResty由中国 人章亦春发起,提供了很多高质量的第三方模块。OpenResty 是一个强大的 Web 应用服务器,OpenResty可以快速构造出 足以胜任10K 乃至1000K以上并发连接响应的超高性能 Web 应用系统。
360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度 用户。

简单理解:OpenResty 封装了ngnix 集成了lua脚本,为开发人员提供了模板实现了相关的逻辑

3.环境配置

1.在linux上安装nginx,lua,redis,
本案例指定nginx的配置文件根目录为root 权限为root
目的就是将来要使用lua脚本的时候 直接可以加载在root下的lua脚本。(lua脚本存放在root下)

修改/openresty/nginx/conf/nginx.conf,

#user nobody; 配置文件第一行原来为这样, 现改为下面的配置 
user root root;

4.缓冲预热

4.1代码分析

需求:需要在页面上显示轮播图(有不同位置)的信息。
1.定义请求,用于查询数据库更新到redis

  1. 连接mysql,按照广告分类ID读取广告列表,转换json字符串
  2. 连接redis,将广告列表json字符串存入redis

定义请求

请求 /ad_update
参数 position(指定的广告位置)
json

2.在/root/lua目录下(配置了nginx加载的根目录)创建ad_load.lua,实现mysql查询数据并存储到redis

ngx.header.content_type="application/json;charset=utf8"  
local cjson = require("cjson")   									--引入模块
local mysql = require("resty.mysql") 								--引入mysql模块
local uri_args = ngx.req.get_uri_args() 						
local position = uri_args["position"] 								--指定参数,position是广告的位置 
local db = mysql:new() 												--初始化数据库
db:set_timeout(1000) 												--设置超时时间
local props = {
      	
host = "192.168.xxx.xxx",											--mysql ip地址 
port = 3306, 														--mysql  端口
database = "changgou_business", 									--mysql 数据库
user = "root", password = "root" 									--用户名密码
}
local res = db:connect(props) 										--获得mysql连接
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") 								--引入redis
local red = redis:new() red:set_timeout(2000) 						--初始化 设置超时时间
local ip ="192.168.200.128" 
local port = 6379 red:connect(ip,port) 
red:set("ad_"..position,cjson.encode(res))                           --存储到redis ..为拼接符 key:ad_广告位置 value:json串
red:close() 
ngx.say("{flag:true}")

修改openresty/nginx/conf/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; 
server {
      
	listen 80; 
	server_name localhost; 
	charset utf‐8; 
	#access_log logs/host.access.log main; 
	# 添加 
	location /ad_update {
      
	content_by_lua_file /root/lua/ad_update.lua; 
	}
# redirect server error pages to the static page /50x.html 
#
	error_page 500 502 503 504 /50x.html; 
	location = /50x.html {
      
	root html;
		}
	}
}

3.最后重启 nginx
在sbin目录下 ./nginx -s reload

小结

预热缓存的具体过程,首先定义好一条请求,访问nginx,会查询数据库,然后返回给ngnix,
存入到redis.具体nginx会执行lua脚本中的脚本,先引入数据库模块,再配置数据库信息获得连接,
执行sql语句,再引入redis模块,配置信息,存储到redis中,当然需要在nginx的配置文件中配置好请求路径需要执行的lua脚本

5.轮播图缓存读取

实现思路:
通过lua脚本直接从redis中获取数据即可
1.定义请求

请求:/ad_read 
参数:position 
返回值:json

2.在/root/lua目录下创建ad_read.lua

ngx.header.content_type="application/json;charset=utf8" 
local uri_args = ngx.req.get_uri_args(); 
local position = uri_args["position"]; 
local redis = require("resty.redis"); 
local red = redis:new() 
red:set_timeout(2000) 
local ok, err = red:connect("192.168.200.128", 6379) 
local rescontent=red:get("ad_"..position) 
ngx.say(rescontent) 
red:close()

在/usr/local/openresty/nginx/conf/nginx.conf中server下添加配置

location /ad_read {
      
content_by_lua_file 
/root/lua/ad_read.lua; 
}

小结:

定义一个查询请求,
在nginx配置文件中配置请求路径需要执行的lua脚本,/root/lua中目录,在lua脚本中引入redis,配置信息,参数作为key查询数据

6.二级缓存

当请求都到redis中,redis压力也会很大,一般采取多级缓存,减少下游服务器压力,

先查询openresty本地缓存,如果没有再查询redis中的数据

openresty本地缓存的操作

1.修改/root/lua目录下ad_read.lua文件

ngx.header.content_type="application/json;charset=utf8" 
local uri_args = ngx.req.get_uri_args(); 
local position = uri_args["position"]; 
local cache_ngx = ngx.shared.dis_cache; 
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("192.168.200.128", 6379) 
	local rescontent=red:get("ad_"..position) 
	ngx.say(rescontent) 
	red:close() 
	cache_ngx:set('ad_cache_'..position, rescontent, 10*60); 
else
	ngx.say(adCache) 
end

说明:ngx.shared.dis_cache;表示开启本地缓存,在本地缓存中没有数据就会查询redis,如果有就直接放回

2.修改nginx配置文件vi /usr/local/openresty/nginx/conf/nginx.conf ,http节点下添加配置:

#包含redis初始化模块 
lua_shared_dict dis_cache 5m; #共享内存开启

说明:该配置是指开启内存

小结

实现本地缓存,是为了减轻redis的压力,配置了每10分钟会去redis进行数据同步,实现本地缓存,
首先在本地缓存中查找数据,没有就去查询redis,有就直接返回

你可能感兴趣的:(nginx,redis)