前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenResty实战系列 | Redis协程网络库 lua-resty-redis

OpenResty实战系列 | Redis协程网络库 lua-resty-redis

作者头像
Tinywan
发布2024-07-30 16:10:52
990
发布2024-07-30 16:10:52
举报
文章被收录于专栏:开源技术小栈

简介

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

代码语言:javascript
复制
opm get openresty/lua-resty-redis

版本信息

代码语言:javascript
复制
# 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文件

代码语言:javascript
复制
--[[-----------------------------------------------------------------------      
* |  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脚本测试请求打印结果

代码语言:javascript
复制
$ 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客户端输出以下内容:

代码语言:javascript
复制
failed to authenticate: ERR invalid password

事务支持

这个库支持Redis事务redis_transactions_test.lua 文件

代码语言:javascript
复制
--[[-----------------------------------------------------------------------      
* |  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脚本测试请求打印结果

代码语言:javascript
复制
$ 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服务。无论是简单的缓存解决方案还是复杂的分布式系统,它都能提供稳定且高效的支撑。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 应用场景
  • 主要特点
  • 安装
  • 基础使用
  • 事务支持
  • 小结
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档