openresty使用redis作本地缓存
一,为什么要使用redis作本地缓存?
1,使用缓存通常会有三层
当使用openresty作为web服务器时,我们更看重是的它可以通过lua编程的扩展能力,就openresty而言,它可以实现的功能非常多,
提高响应速度是web服务中非常重要的功能,
使用缓存通常会有三层:
本地缓存:存在于本地机器上,直接通过nginx访问,避免网络io;
redis cluster:存储更多的供lua访问的数据,也是通过nginx访问直接返回,相比前一层缓存,增加了网络io,但仍然避免了对业务系统的访问;
业务缓存:供运行在tomcat/php-fpm/go http中内的业务代码访问。
可以比较得到本地缓存是响应速度最快的,通常可以在10ms内对请求进行响应。
我们看到的很多经过优化的BAT等大厂的站点都能在极短时间内响应请求,就是经过了层层优化的结果。
2,这里会提供一个例子:使用redis做商品详情页的cache:
流程:当用户访问时,
先从redis中获取cache内容,
如果redis中不存在此value,则会改为访问后端业务系统获取cache
说明:在生产环境中,为方便更新,通常会采用redis的主从架构,
每台业务nginx上所配备的redis的数据能得到实时更新
说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,nginx的配置文件:
- upstream backenditem {
- server 127.0.0.1:8000;
- }
- server {
- listen 8000;
- server_name 8000.test.com;
- location / {
- default_type 'text/html';
- content_by_lua_block {ngx.say("hello world,this is path backend from 8000:uri:"..ngx.var.request_uri)}
- }
- }
- server {
- listen 82;
- server_name test.com;
- location ~ /backenditem/(.*) {
- rewrite /backenditem(/.*) $1 break;
- proxy_next_upstream error timeout;
- proxy_pass http://backenditem;
- }
- location /item {
- default_type text/html;
- content_by_lua_file /data/luacache/webroot/item_redis_cache.lua;
- }
- location / {
- default_type 'text/html';
- content_by_lua_block {ngx.say("default path:uri:"..ngx.var.request_uri)}
- }
- }
说明:1,端口8000的server是一个demo,生产环境中,它应该是使用tomcat/php-fpm/django之类的业务系统
2,location ~ /backenditem/(.*) :负责upstream到后端业务系统,
注意这里要做一次 rewrite /backenditem(/.*) $1 break; ,作用是去掉用来标识要跳转到后端的backenditem字串
3,content_by_lua_file 此处用绝对路径指定了lua代码的程序文件
三,lua程序文件: item_redis_cache.lua
- --指定要访问的lua包所在的路径
- package.path = package.path..";/data/luacache/webroot/config/?.lua;/data/luacache/webroot/lib/?.lua"
- local config = require "config_constant"
- local readhttp = require "read_http"
- local returnjson = require "return_json"
- --redis连接池工厂
- local redis_factory = require('redis_factory')(config.redisConfig)
- --获取redis的连接实例
- local ok, redis_a = redis_factory:spawn('redis_a')
- --用于接收前端数据的对象
- local args=nil
- --获取前端的请求方式 并获取传递的参数
- local request_method = ngx.var.request_method
- --判断是get请求还是post请求并分别拿出相应的数据
- if "GET" == request_method then
- args = ngx.req.get_uri_args()
- elseif "POST" == request_method then
- ngx.req.read_body()
- args = ngx.req.get_post_args()
- --兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug
- if (args == nil or args.data == null) then
- args = ngx.req.get_uri_args()
- end
- end
- --ngx.log(ngx.ERR,"args.key:",args.key)
- if args.itemid == nil or args.itemid=="" then
- local json = returnjson.getjson("1",'key not exist or key is empty',"")
- --ngx.log(ngx.ERR,"json:",json)
- ngx.say(json)
- else
- --获取前端传递的itemid
- local itemid = args.itemid
- --在redis中获取itemid对应的值
- local va = redis_a:get(itemid)
- if va == ngx.null or va == nil then
- --ngx.log(ngx.ERR, "redis not found content, back to http, itemid : ", itemid)
- local url="/backenditem/item"
- va = readhttp.read(url,itemid)
- ngx.print(returnjson.getjson(0,itemid,va))
- else
- --响应前端
- ngx.say(returnjson.getjson(0,itemid,va))
- end
- end
四,lua访问redis的配置文件: config_constant.lua
- config = {}
- config.redisConfig = {
- redis_a = { -- your connection name
- --ip
- host = '127.0.0.1',
- --端口
- port = 6379,
- --密码
- pass = '',
- --超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200
- timeout = 120000,
- --redis的库
- database = 0,
- },
- }
- return config
五,lua程序文件:read_http.lua:用来从后端业务系统得到response
- local read_http = {}
- function read_http.read(url,id)
- local resp = ngx.location.capture(url, {
- method = ngx.HTTP_GET,
- args = {id = id}
- })
- if not resp then
- ngx.log(ngx.ERR, "request error :", err)
- return
- end
- if resp.status ~= 200 then
- ngx.log(ngx.ERR, "request error, status :", resp.status)
- return
- end
- return resp.body
- end
- return read_http
六,lua程序:return_json.lua :返回json字串
- local return_json = {}
- function return_json.getjson(status,msg,data)
- local json = '{"status":"'..status..'","msg":"'..msg..'","data":"'..data..'"}'
- return json
- end
- return return_json
七,此项目的github地址:
- https://github.com/liuhongdi/luacache
八,测试效果:
1,当有商品存在于redis中的返回 :如图
2,当商品不存在于redis中的返回: 如图
3,当参数错误时的返回 :如图
九,文中涉及到的各平台的版本查看:
- [root@localhost luacache]# cat /etc/redhat-release
- CentOS Linux release 8.1.1911 (Core)
- [root@localhost luacache]# /usr/local/openresty/bin/openresty -V
- nginx version: openresty/1.15.8.2
- built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC)
- built with OpenSSL 1.1.0k 28 May 2019
- TLS SNI support enabled
- [root@localhost luacache]# /usr/local/soft/redis5/bin/redis-server --version
- Redis server v=5.0.7 sha=00000000:0 malloc=libc bits=64 build=8e31d2ed9a4c9593
openresty使用redis作本地缓存的更多相关文章
- springboot+mybatis 用redis作二级缓存
1.加入相关依赖包: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- 本地缓存google.guava及分布式缓存redis 随笔
近期项目用到了缓存,我选用的是主流的google.guava作本地缓存,redis作分布式 缓存,先说说我对本地缓存和分布式缓存的理解吧,可能不太成熟的地方,大家指出,一起 学习.本地缓存的特点是速度 ...
- lua模块demo(redis,http,mysql,cjson,本地缓存)
1. lua模块demo(redis,http,mysql,cjson,本地缓存) 1.1. 配置 在nginx.conf中设置lua_shared_dict my_cache 128m; 开启ngi ...
- 本地缓存,Redis缓存,数据库DB查询(结合代码分析)
问题背景 为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级? 一.为什么要使用缓存 原因:CPU的速度远远高于磁盘IO的速度问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作所 ...
- redis订阅发布消息操作本地缓存
Redis 本地缓存+远程缓存方案 使用纯java的ehcache作为本地缓存 Reids 作为远程分布式缓存 解决redis缓存压力过大,提高缓存速度,以及缓存性能. Redis和ehcache缓存 ...
- 使用本地缓存快还是使用redis缓存好?
使用本地缓存快还是使用redis缓存好? Redis早已家喻户晓,其性能自不必多说. 但是总有些时候,我们想把性能再提升一点,想着redis是个远程服务,性能也许不够,于是想用本地缓存试试!想法是不错 ...
- 缓存子系统如何设计(Cachable tag, Memcache/redis support, xml config support, LRU/LFU/本地缓存命中率)
大家对这段代码肯定很熟悉吧: public List<UserInfo> SearchUsers(string userName) { string cacheKey=string.For ...
- 用Redis作Mysql数据库缓存
使用redis作mysql数据库缓存时,需要考虑两个问题: 1.确定用何种数据结构存储来自Mysql的数据; 2.在确定数据结构之后,用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是按 ...
- redis(二)--用Redis作MySQL数据库缓存
用Redis作MySQL数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...
随机推荐
- synchronized的实现原理——锁膨胀过程
@ 目录 前言 正文 偏向锁 轻量锁 批量重偏向 批量撤销 重量锁 总结 前言 上一篇分析了优化后的synchronized在不同场景下对象头中的表现形式,还记得那个结论吗?当一个线程第一次获取锁后再 ...
- NetCore微服务实战体系:日志管理
一. 起始 进入NetCore时代,日志的使用有了很大的变化,因为跨平台以及虚拟化技术的使用,日志不能够再像Framework的方式直接记录在文本,文本其实也可以,但是日志的管理以及查看都不太方便.L ...
- defer implement for C/C++ using GCC/Clang extension
前述: go 中defer 给出了一种,延时调用的方式来释放资源.但是对于C/C++去没有内置的这种属性.对于经常手动管理内存的C/C++有其是C程序员这种特性显得无比重要.这里给出了一种基于GCC/ ...
- [Java并发编程之美]第2章 synchroized关键字
###synchronized关键字 synchronized块是Java提供的一种原子性内置锁,每个对象都可以把它当同步锁来用.线程在进入synchronized块钱会自动获取内部锁,这时候其他线程 ...
- js中模拟移动端长按效果
我们都知道 js 是有onmousedown(鼠标按下事件)和onmouseup(鼠标抬起事件),刚开始我的思路是 鼠标抬起时间减去鼠标按下时间 var oDiv = document.getElem ...
- 3.Kafka集群配置
- JVM学习(六)JVM常见知识问答
文章更新时间:2020/04/21 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java虚拟机是一个可以执行Java字节码的虚拟机进程. Java源文 ...
- Layer层自定义
keras允许自定义Layer层, 大大方便了一些复杂操作的实现. 也方便了一些novel结构的复用, 提高搭建模型的效率. 实现方法 通过继承keras.engine.Layer类, 重写其中的部分 ...
- ksoap2-android的简单使用
soap2-android 官网地址 https://simpligility.github.io/ksoap2-android/index.html 发行版本 https://oss.sonatyp ...
- P 4315 月下毛景树
题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树&quo ...