1. 当我们聊缓存时在聊什么?
想象你经营着一家网红奶茶店,每次顾客点单都要从仓库拿原料(这就像服务器每次都要访问数据库)。但聪明的店长会把常用原料放在前台货架(这就是缓存),OpenResty就是这个帮你搭建智能货架的技术管家。它基于Nginx和LuaJIT,能用Lua脚本灵活控制缓存逻辑。
2. 快速搭建缓存工作台
2.1 基础配置(技术栈:OpenResty 1.21+)
http {
# 加载Lua模块
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
# 创建共享字典(相当于公共储物柜)
lua_shared_dict my_cache 128m; # 128MB内存空间
server {
listen 80;
location /api {
# 交给Lua脚本处理
content_by_lua_block {
-- 后续章节的代码都会放在这里
}
}
}
}
2.2 缓存读写示例
-- 获取请求参数
local product_id = ngx.var.arg_id
-- 从缓存储物柜拿数据
local cache = ngx.shared.my_cache
local cached_data = cache:get(product_id)
if cached_data then
ngx.say("从缓存获取:", cached_data)
return
end
-- 缓存未命中时查询数据库(模拟)
local db_data = "商品详情_"..product_id
ngx.sleep(0.1) -- 模拟数据库查询耗时
-- 存入缓存(设置5分钟有效期)
cache:set(product_id, db_data, 300)
ngx.say("从数据库获取:", db_data)
3. 高阶玩法:缓存失效策略
3.1 批量清除缓存
-- 接收POST请求清除指定缓存
if ngx.req.get_method() == "POST" then
ngx.req.read_body()
local post_args = ngx.req.get_post_args()
-- 遍历清除多个key
for key, _ in pairs(post_args) do
ngx.shared.my_cache:delete(key)
ngx.log(ngx.INFO, "已清除缓存:", key)
end
ngx.say("缓存清理完成")
return
end
3.2 缓存预热策略
-- 启动时预热热点数据
init_worker_by_lua_block {
local cache = ngx.shared.my_cache
local hot_items = {"top1", "top2", "top3"}
for _, item in ipairs(hot_items) do
if not cache:get(item) then
cache:set(item, "预热数据_"..item, 600)
end
end
}
4. 应用场景分析
4.1 高并发读取场景
- 典型场景:电商秒杀商品详情页
- 实战技巧:采用"缓存穿透保护+异步更新"组合拳
-- 带锁查询防止缓存击穿
local lock_key = product_id.."_lock"
if not cache:get(product_id) then
if cache:add(lock_key, true, 2) then -- 设置2秒锁
-- 只有获得锁的请求去查库
local db_data = query_db(product_id)
cache:set(product_id, db_data, 300)
cache:delete(lock_key)
else
-- 其他请求等待100ms后重试
ngx.sleep(0.1)
cached_data = cache:get(product_id)
end
end
4.2 动态内容缓存
- 典型场景:个性化推荐系统
- 处理方案:带参数签名校验
-- 生成参数签名
local params = ngx.req.get_uri_args()
local signature = ngx.md5(ngx.encode_args(params))
-- 使用签名作为缓存key
local cache_key = "recommend_"..signature
local data = cache:get(cache_key)
if not data then
data = generate_recommend(params)
cache:set(cache_key, data, 60) -- 短时间缓存
end
5. 技术选型优劣谈
5.1 闪光点
- 速度王者:内存级响应(<1ms访问速度)
- 容量自由:支持GB级内存分配
- 灵活之王:Lua脚本实现复杂逻辑
- 集群支持:可与Redis组成二级缓存
5.2 需要注意的坑
- 内存刺客:不控制的话容易撑爆内存
- 雪崩风险:批量失效可能引发数据库压力
- 数据一致:需要自己实现同步机制
- 类型限制:只能存储字符串类型数据
6. 避坑指南
- 内存水位监控:建议设置共享字典使用率告警
- Key命名规范:建议使用"业务_模块_参数"结构
- 过期时间随机化:避免同一时间大量失效
- 版本兼容性:注意不同OpenResty版本的API差异
- 压力测试:建议使用wrk进行基准测试
7. 总结与展望
OpenResty的缓存就像给服务器装上了涡轮增压器,通过本文的配置示例和场景分析,我们可以看到它特别适合需要快速响应但数据更新不频繁的场景。虽然需要开发者自己把控很多细节,但带来的性能提升是显著的。
未来发展方向可以关注:与Kubernetes生态的深度整合、自动内存优化算法的引入、机器学习驱动的智能缓存策略等。建议读者从简单的页面缓存开始实践,逐步过渡到复杂的业务场景,同时注意做好监控和熔断机制。