OpenResty实战系列 | 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

opm get openresty/lua-resty-redis

版本信息

# 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文件

--[[-----------------------------------------------------------------------      
* |  Copyright (C) Shaobo Wan (Tinywan) 
* |------------------------------------------------------------------------
--]]


-- redis config
local redis = require "resty.redis"
local red = redis:new()

red:set_timeouts(100010001000-- 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(10000100)
 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脚本测试请求打印结果

$ 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 文件

--[[-----------------------------------------------------------------------      
* |  Copyright (C) Shaobo Wan (Tinywan) 
* |------------------------------------------------------------------------
--]]


local cjson = require "cjson"

-- redis config
local redis = require "resty.redis"
local red = redis:new()

red:set_timeouts(100010001000-- 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脚本测试请求打印结果

$ 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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/296823.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!