HM-SpringCloud微服务系列11.3.6【实现多级缓存(5)】
7. Nginx本地缓存
现在,整个多级缓存中只差最后一环,也就是nginx的本地缓存了。如图:
7.1 本地缓存API
OpenResty为Nginx提供了shard dict的功能,可以在nginx的多个worker之间共享数据,实现缓存功能。
7.1.1 开启共享字典
在nginx.conf的http下添加配置:
# 共享字典,也就是本地缓存,名称叫做:item_cache,大小150m
lua_shared_dict item_cache 150m;
7.1.2 操作共享字典
在item.lua中导入并使用本地缓存:
-- 获取本地缓存对象
local item_cache = ngx.shared.item_cache
-- 以下为操作示例
-- 存储, 指定key、value、过期时间,单位s,默认为0代表永不过期
item_cache:set('key', 'value', 1000)
-- 读取
local val = item_cache:get('key')
7.2 实现本地缓存查询[案例]
7.2.1 案例需求
7.2.2 实现
1)修改/usr/local/openresty/lua/item.lua
文件,修改read_data查询函数,添加本地缓存逻辑:
-- 封装查询函数(expire是有效期)
function read_data(key, expire, path, params)
-- 查询本地缓存
local val = item_cache:get(key)
if not val then
ngx.log(ngx.ERR, "本地缓存查询失败,尝试查询redis, key: ", key)
-- 查询redis本地缓存
val = read_redis("127.0.0.1", 6379, key)
-- 因为本代码是由openResty运行的,而redis和openResty都在同一台虚拟机中,127.0.0.1代表本地
-- 判断redis查询结果
if not val then
ngx.log(ngx.ERR, "redis查询失败,尝试查询http, key: ", key)
-- redis查询失败,去查询http
val = read_http(path, params)
end
end
-- 查询成功,先把数据写入本地缓存
item_cache:set(key, val, expire)
-- 然后再返回数据
return val
end
2)修改item.lua中查询商品和库存的业务,实现最新的read_data函数:
-- 根据id查询商品
-- local itemJSON = read_http("/item/" .. id, nil)
-- local itemJSON = read_data("item:id:" .. id, "/item/" .. id, nil)
local itemJSON = read_data("item:id:" .. id, 1800, "/item/" .. id, nil)
-- 根据id查询商品库存
-- local itemStockJSON = read_http("/item/stock/" .. id, nil)
-- local itemStockJSON = read_data("item:stock:id:" .. id, "/item/stock/" .. id, nil)
local itemStockJSON = read_data("item:stock:id:" .. id, 60, "/item/stock/" .. id, nil)
其实就是多了缓存时间参数,过期后nginx缓存会自动删除,下次访问即可更新缓存。
这里给商品基本信息设置超时时间为30分钟,库存为1分钟。
因为库存更新频率较高,如果缓存时间过长,可能与数据库差异较大。
3)完整的item.lua文件:
-- 引入自定义common工具模块,返回值是common中返回的 _M
local common = require("common")
-- 从 common中获取函数
local read_http = common.read_http
local read_redis = common.read_redis
-- 导入cjson库
local cjson = require("cjson")
-- 导入共享词典,获取本地缓存对象
local item_cache = ngx.shared.item_cache
-- 封装查询函数(expire是有效期)
function read_data(key, expire, path, params)
-- 查询本地缓存
local val = item_cache:get(key)
if not val then
ngx.log(ngx.ERR, "本地缓存查询失败,尝试查询redis, key: ", key)
-- 查询redis本地缓存
val = read_redis("127.0.0.1", 6379, key)
-- 因为本代码是由openResty运行的,而redis和openResty都在同一台虚拟机中,127.0.0.1代表本地
-- 判断redis查询结果
if not val then
ngx.log(ngx.ERR, "redis查询失败,尝试查询http, key: ", key)
-- redis查询失败,去查询http
val = read_http(path, params)
end
end
-- 查询成功,先把数据写入本地缓存
item_cache:set(key, val, expire)
-- 然后再返回数据
return val
end
-- 获取路径参数
local id = ngx.var[1]
-- 根据id查询商品
-- local itemJSON = read_http("/item/" .. id, nil)
-- local itemJSON = read_data("item:id:" .. id, "/item/" .. id, nil)
local itemJSON = read_data("item:id:" .. id, 1800, "/item/" .. id, nil)
-- 根据id查询商品库存
-- local itemStockJSON = read_http("/item/stock/" .. id, nil)
-- local itemStockJSON = read_data("item:stock:id:" .. id, "/item/stock/" .. id, nil)
local itemStockJSON = read_data("item:stock:id:" .. id, 60, "/item/stock/" .. id, nil)
-- JSON转换为lua的table(反序列化)
local item = cjson.decode(itemJSON)
local stock = cjson.decode(itemStockJSON)
-- 组合数据(item中原本没有但现在需要的数据去stock中取)
item.stock = stock.stock
item.sold = stock.sold
-- 把item序列化为json返回结果
ngx.say(cjson.encode(item))
7.2.3 测试
通过查看日志文件进行验证nginx本地缓存是否生效
访问http://localhost/item.html?id=10001
可以看到第一次访问时,本地缓存中并没有数据,需要去查询redis
此时,再去刷新几次页面,重新访问几次
可以看到并没有输出“本地缓存查询失败”,说明刚刚第一次访问时,redis查完后先存入了本地缓存,而之后的访问就可以直接从本地缓存中查询了而不需再走redis
PS:红×掉的报错是因为前后两次访问时间间隔过长,超过了过期时间QAQ
此时,实际上就算删掉redis中10001的数据,也可以正常访问,因为本地缓存中已有数据
而且可以发现,走本地缓存时,速度非常快,仅耗时6ms
分类:
微服务
标签:
SpringCloud
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!