ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
Redis协程网络库 lua-resty-redis ## 简介 lua-resty-redis 是由著名OpenResty社区成员Agent Zhang(章亦春)创建的。这是一个与OpenResty集成的Lua模块,允许你在Nginx环境中直接进行Redis操作。利用OpenResty的强大功能,lua-resty-redis提供了异步非阻塞的Redis API,帮助开发者构建高性能、高并发的应用。 lua-resty-redis的核心在于其非阻塞I/O模型。它基于OpenResty的ngx.socket.tcp()接口实现,利用了LuaJIT的高效性能和Nginx事件循环机制。这意味着在处理大量并发请求时,即使Redis服务器繁忙,也不会导致Nginx的工作线程被阻塞,从而提高了整体系统的响应速度。 此外,该库提供了丰富的Redis命令支持,包括但不限于数据读写、哈希操作、集合操作、有序集合、发布订阅等。它的API清晰简洁,易于理解和使用,使得你可以快速地将Redis功能融入到你的OpenResty应用程序中。 ## 应用场景 * 缓存管理:利用Redis的高速读写能力,可以作为动态内容的高速缓存层,降低对后端数据库的压力。 * 分布式会话:借助lua-resty-redis,可以在多台服务器之间共享用户的会话状态。 * 消息队列:通过其发布的订阅功能,可以构建简单的消息队列系统,实现任务的异步处理。 * 实时数据分析:利用Redis的数据结构,如计数器、集合等,进行实时统计和分析。 ## 主要特点 * 非阻塞I/O - 基于OpenResty的异步TCP套接字接口,确保高并发场景下的效率。 * Redis命令支持 - 提供了Redis的所有主要命令,方便你执行各种操作。 * 错误处理 - 提供了良好的错误处理机制,便于定位和解决问题。 * 可扩展性 - 可以自定义连接池策略,适应不同规模和需求的系统。 * 简洁API - 易于理解和使用的API,加速开发过程。 ## 安装 这里通过OPM工具包安装,更多请查看[OpenResty实战系列 | 包管理工具OPM和LuaRocks](https://mp.weixin.qq.com/s/s6-fukvBWdMuYRDa-cYZHw) ```lua opm get openresty/lua-resty-redis ``` 版本信息 ```lua # opm info openresty/lua-resty-redis Name : lua-resty-redis Version : 0.27 Abstract : Lua redis client driver for the ngx_lua based on the cosocket API Author : Yichun "agentzh" Zhang (agentzh) Account : openresty Code Repo : https://github.com/openresty/lua-resty-redis License : BSD 2-Clause "Simplified" or "FreeBSD" license Original Work : yes ``` ## 基础使用 使用 lua-resty-redis 设置和获取一个键值对基本示例 `redis_test_01.lua`文件 ```lua --[[----------------------------------------------------------------------- * | Copyright (C) Shaobo Wan (Tinywan) * |------------------------------------------------------------------------ --]] -- redis config local redis = require "resty.redis" local red = redis:new() red:set_timeouts(1000, 1000, 1000) -- 1 秒 -- 通过宿主机链接 local ok, err = red:connect("192.168.13.168", 6379) if not ok then ngx.say("[x] failed to connect: ", err) return end -- 设置权限 local res, err = red:auth("123456") if not res then ngx.say("[x] failed to authenticate: ", err) return end -- 设置权限 -- 请注意这里 auth 的调用过程 local count, err = red:get_reused_times() ngx.say("[x] get_reused_times count: ", count) if 0 == count then res, err = red:auth("123456") if not res then ngx.say("[x]failed to authenticate: ", err) return end elseif err then ngx.say("[x]failed to get reused times: ", err) return end ngx.say("[x] set result: ", ok) local res, err = red:get("name") if not res then ngx.say("[x] failed to get name: ", err) return end if res == ngx.null then ngx.say("[x] name not found.") return end ngx.say("[x] get name : ", res) -- 连接池大小是100个,并且设置最大的空闲时间是 10 秒 local ok, err = red:set_keepalive(10000, 100) if not ok then ngx.say("[x] failed to set keepalive: ", err) return end ``` > **`red:get_reused_times()`方法** * 如果当前连接不是从内建连接池中获取的,该方法总是返回 `0` ,也就是说,该连接还没有被使用过。 * 如果连接来自连接池,那么返回值永远都是非零。 这个方法可以用来确认当前连接是否来自池子。对于 Redis 授权,实际上只需要建立连接后,首次认证一下,后面只需直接使用即可。换句话说,从连接池中获取的连接都是经过授权认证的,只有新创建的连接才需要进行授权认证。所以大家就看到了 `count, err = red:get\_reused\_times()` 这段代码,并有了下面 `if 0 == count then` 的判断逻辑。 > 通过curl脚本测试请求打印结果 ```lua $ curl -i http://openresty.tinywan.com/lua_redis_test HTTP/1.1 200 OK Server: openresty/1.17.8.2 Date: Tue, 23 Jul 2024 07:16:23 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding [x] set result: OK [x] get name : Tinywan ``` 如果指定的密码是错误的,那么上面的示例将向HTTP客户端输出以下内容: ``` failed to authenticate: ERR invalid password ``` ## 事务支持 这个库支持Redis事务 `redis_transactions_test.lua` 文件 ```lua --[[----------------------------------------------------------------------- * | Copyright (C) Shaobo Wan (Tinywan) * |------------------------------------------------------------------------ --]] local cjson = require "cjson" -- redis config local redis = require "resty.redis" local red = redis:new() red:set_timeouts(1000, 1000, 1000) -- 1 秒 -- 通过宿主机链接 local ok, err = red:connect("192.168.13.168", 6379) if not ok then ngx.say("[x] failed to connect: ", err) return end -- 设置权限 local res, err = red:auth("123456") if not res then ngx.say("[x] failed to authenticate: ", err) return end -- 设置权限 local ok, err = red:multi() if not ok then ngx.say("failed to run multi: ", err) return end ngx.say("[x] multi ans: ", cjson.encode(ok)) local ans, err = red:set("resty_name", "Tinywan") if not ans then ngx.say("[x] failed to run sort: ", err) return end ngx.say("[x] set ans: ", cjson.encode(ans)) local ans, err = red:lpop("resty_name") if not ans then ngx.say("[x] failed to run sort: ", err) return end ngx.say("[x] set ans: ", cjson.encode(ans)) ans, err = red:exec() ngx.say("[x] exec ans: ", cjson.encode(ans)) red:close() ``` 通过curl脚本测试请求打印结果 ```lua $ curl -i http://openresty.tinywan.com/lua_redis_transactions_test HTTP/1.1 200 OK Server: openresty/1.17.8.2 Date: Tue, 23 Jul 2024 07:29:53 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding [x] multi ans: "OK" [x] set ans: "QUEUED" [x] set ans: "QUEUED" [x] exec ans: ["OK",[false,"WRONGTYPE Operation against a key holding the wrong kind of value"]] ``` ## 小结 lua-resty-redis是一个强大的工具,能够帮助开发者充分利用OpenResty和Redis的优势,构建高性能的Web服务。无论是简单的缓存解决方案还是复杂的分布式系统,它都能提供稳定且高效的支撑。如果你正在寻找一个在OpenResty环境中操作Redis的解决方案,那么lua-resty-redis绝对值得一试!