Lua脚本中MySQL数据缓存的实现方法咨询
看来你被频繁MySQL查询的卡顿问题折腾得不轻,我给你几个在Lua环境里实现数据缓存的靠谱方案,应该能解决你的痛点:
1. 本地内存缓存(轻量首选)
Lua本身的table天然可以作为内存缓存容器,适合存储查询频繁、更新少、数据量不大的内容,完全无额外依赖,速度最快。
你可以封装一个带过期时间的缓存函数,自动处理缓存命中/失效逻辑:
-- 全局缓存表,用查询标识作为key,存储数据+过期时间 local mysql_local_cache = {} -- 缓存通用函数 -- 参数:query_key(唯一标识查询的字符串)、fetch_func(从MySQL取数据的函数)、expire_sec(过期秒数) function get_cached_mysql_data(query_key, fetch_func, expire_sec) local cache_item = mysql_local_cache[query_key] -- 检查缓存是否有效 if cache_item and os.time() < cache_item.expire_at then return cache_item.data end -- 缓存失效,重新从MySQL拉取 local fresh_data = fetch_func() -- 更新缓存 mysql_local_cache[query_key] = { data = fresh_data, expire_at = os.time() + expire_sec } return fresh_data end -- 使用示例:假设你已经有一个从MySQL查询的函数fetch_from_mysql local user_info = get_cached_mysql_data( "user:info:1001", -- 唯一缓存键 function() return fetch_from_mysql("SELECT * FROM users WHERE id=1001") end, 300 -- 5分钟后过期 )
优缺点:
- ✅ 零额外依赖、速度极快
- ❌ 进程重启后缓存全部丢失;内存有限,不适合存大量数据;多进程场景下缓存不共享
2. 分布式Redis缓存(多进程/大数据量场景)
如果你的Lua脚本是在多进程环境(比如OpenResty)运行,或者需要缓存大量数据,Redis是最优选择——它支持持久化、分布式共享,性能远高于MySQL。
以OpenResty常用的lua-resty-redis库为例:
local redis = require "resty.redis" local cjson = require "cjson" -- 初始化Redis连接 local red = redis:new() red:set_timeout(1000) -- 1秒超时 local ok, err = red:connect("127.0.0.1", 6379) if not ok then -- Redis连接失败,降级到直接查MySQL ngx.log(ngx.ERR, "Redis连接失败: ", err) return fetch_from_mysql("SELECT * FROM goods WHERE category=1") end -- 尝试从Redis取缓存 local cache_key = "mysql:goods:category:1" local cached_str = red:get(cache_key) if cached_str then -- 缓存命中,解析后返回 return cjson.decode(cached_str) end -- 缓存未命中,查MySQL local goods_list = fetch_from_mysql("SELECT * FROM goods WHERE category=1") -- 将数据转JSON存入Redis,设置300秒过期 local ok, err = red:setex(cache_key, 300, cjson.encode(goods_list)) if not ok then ngx.log(ngx.ERR, "Redis缓存写入失败: ", err) end return goods_list
优缺点:
- ✅ 支持多进程共享、数据持久化、可存储大量数据
- ❌ 需要部署Redis服务,存在少量网络开销(但远低于MySQL查询)
3. 辅助优化:减少MySQL查询压力
除了缓存,这些小技巧也能大幅缓解卡顿:
- 给查询字段加索引:避免全表扫描,这是最基础也最有效的优化
- 批量查询:把多次单条查询合并成一次批量查询(比如
SELECT * FROM users WHERE id IN (1,2,...100)) - 避免重复查询:在脚本逻辑里先判断是否已经取过相同数据,不要重复调用查询接口
缓存注意事项
- 缓存失效策略:除了TTL过期,当MySQL数据更新时,要主动删除对应的缓存键,避免返回脏数据
- 缓存键设计:用清晰的命名规则(比如
表名:字段:条件),避免键冲突 - 本地缓存清理:如果用内存缓存,建议定期遍历缓存表删除过期条目,防止内存溢出
内容的提问来源于stack exchange,提问作者btwlouis
相关产品推荐
相关产品推荐

