鍍金池/ 教程/ Java/ 動態(tài)生成的 lua-resty-redis 模塊方法
定時任務(wù)
函數(shù)的參數(shù)
超時
一個 openresty 內(nèi)存“泄漏”問題
獲取 uri 參數(shù)
局部變量
sleep
灰度發(fā)布
TIME_WAIT
代碼覆蓋率
連接池
CentOS 平臺安裝
稀疏數(shù)組
如何只啟動一個 timer 工作?
變量的共享范圍
break,return 關(guān)鍵字
Nginx
SQL 注入
如何引用第三方 resty 庫
不同階段共享變量
獲取請求 body
動態(tài)生成的 lua-resty-redis 模塊方法
動態(tài)加載證書和 OCSP stapling
repeat 控制結(jié)構(gòu)
編碼為 array 還是 object
Nginx 靜態(tài)文件服務(wù)
執(zhí)行階段概念
Lua 函數(shù)
日期時間函數(shù)
健康監(jiān)測
與其他 location 配合
for 控制結(jié)構(gòu)
函數(shù)定義
HTTPS 時代
點號與冒號操作符的區(qū)別
String 庫
文件操作
OpenResty 最佳實踐
<code>ngx.shared.DICT</code> 非隊列性質(zhì)
使用動態(tài) DNS 來完成 HTTP 請求
代碼規(guī)范
什么是 JIT?
Windows 平臺安裝
正確的記錄日志
LuaNginxModule
不用標(biāo)準(zhǔn)庫
C10K 編程
控制結(jié)構(gòu)
請求中斷后的處理
Lua 環(huán)境搭建
Test::Nginx 能指定現(xiàn)成的 nginx.conf,而不是自動生成一個嗎
Lua 基礎(chǔ)數(shù)據(jù)類型
動態(tài)限速
PostgresNginxModule
簡單API Server框架
API 測試
location 匹配規(guī)則
虛變量
單元測試
防止 SQL 注入
select + set_keepalive 組合操作引起的數(shù)據(jù)讀寫錯誤
阻塞操作
全動態(tài)函數(shù)調(diào)用
Web 服務(wù)
典型應(yīng)用場景
Nginx 新手起步
TLS session resumption
輸出響應(yīng)體
調(diào)用代碼前先定義函數(shù)
module 是邪惡的
怎樣理解 cosocket
模塊
Socket 編程發(fā)展
如何對 Nginx Lua module 添加新 api
如何在后臺開啟輕量級線程完成定時任務(wù)?
如何定位問題
table 庫
json 解析的異常捕獲
如何安裝火焰圖生成工具
lua 中如何 continue
if 是邪惡的
為什么我們的域名不能被解析
抵制使用 module() 定義模塊
測試
body 在 location 中的傳遞
Lua 入門
子查詢
pipeline 壓縮請求數(shù)量
如何發(fā)起新 HTTP 請求
Lua 簡介
緩存失效風(fēng)暴
Ubuntu 平臺安裝
日志輸出
緩存
Lua 面向?qū)ο缶幊?/span>
Nginx 陷阱和常見錯誤
Redis 接口的二次封裝(發(fā)布訂閱)
日志
訪問有授權(quán)驗證的 Redis
正則表達(dá)式
lock
熱裝載代碼
調(diào)用 FFI 出現(xiàn) &quot;table overflow&quot;
數(shù)據(jù)合法性檢測
禁止某些終端訪問
控制結(jié)構(gòu) if-else
調(diào)試
與 Docker 使用的網(wǎng)絡(luò)瓶頸
PostgresNginxModule 模塊的調(diào)用方式
用 do-end 整理你的代碼
FFI
什么時候使用
簡介
環(huán)境搭建
Mac OS X 平臺安裝
火焰圖
負(fù)載均衡
while 型控制結(jié)構(gòu)
如何定位 openresty 崩潰 bug
使用 Nginx 內(nèi)置綁定變量
判斷數(shù)組大小
請求返回后繼續(xù)執(zhí)行
Redis 接口的二次封裝
KeepAlive
反向代理
協(xié)議無痛升級
數(shù)學(xué)庫
元表
Vanilla 介紹
HelloWorld
LuaCjsonLibrary
持續(xù)集成
代碼靜態(tài)分析
網(wǎng)上有大量對 Lua 調(diào)優(yōu)的推薦,我們應(yīng)該如何看待?
script 壓縮復(fù)雜請求
非空判斷
性能測試
函數(shù)返回值
API 的設(shè)計
kong 介紹
表達(dá)式
不支持事務(wù)
LuaRestyDNSLibrary 簡介

動態(tài)生成的 lua-resty-redis 模塊方法

剛接觸 lua-resty-redis 的文檔的時候,你可能會驚訝于上面列出的方法之少。 Redis 有好幾十個命令,而Method一節(jié)列出的方法卻寥寥無幾。 事實上,如果仔細(xì)閱讀了文檔,你會在 Method 一節(jié)的開頭讀到這么一段話:

All of the Redis commands have their own methods with the same name except all in lower case. You can find the complete list of Redis commands here: http://redis.io/commands ... In addition to all those redis command methods, the following methods are also provided:

看來不是 lua-resty-redis 支持的方法少,而是大部分方法都不需要單獨列出來。

動態(tài)語言,動態(tài)方法

其實,lua-resty-redis 并沒有顯式定義這一類跟 Redis 命令同名的方法。

熟悉 Redis 的人對 redis.call 應(yīng)該不會感到陌生,這是 Redis Lua 腳本中調(diào)用 Redis 命令的唯一方法。 無論是什么 Redis 命令,你都可以通過它調(diào)用。 lua-resty-redis 內(nèi)部就有一個類似于這樣的方法,它負(fù)責(zé)把請求參數(shù)發(fā)給 Redis,然后處理來自 Redis 的響應(yīng)。

出于易用性,lua-resty-redis 用 $command(arg1, arg2) 的形式封裝了 call($command, arg1, arg2)。每次調(diào)用時可以少打四個字符呢。 由于動態(tài)語言支持動態(tài)生成方法,lua-resty-redis 并不用給每個命令補上一個對應(yīng)的方法,它只需要:

-- 僅為示例,不是真正的實現(xiàn)
local cmds = {
    'get', 'set', ...
}

for i = 1, #cmds do
    local cmd = cmds[i]
    _M[cmd] = function(...)
        call(cmd, ...)
    end
end

現(xiàn)在,要想支持新的 Redis 命令,往 cmds 里加多一個字符串就好了。這就叫良好的拓展性。 當(dāng)然,有些命令,比如 subscribe,需要額外的特殊處理。

動態(tài)方法,惰性生成

從 OpenResty 1.11.2 版本開始,lua-resty-redis 模塊使用了一個巧妙的技巧,推遲到實際需要時才動態(tài)生成模塊方法。 依靠惰性生成方法,要想支持新的 Redis 命令,大多數(shù)情況下 lua-resty-redis 連一個字符串都不用加。無需拓展,才是真正的“良好的拓展性”。

前面說到,動態(tài)語言支持動態(tài)生成方法,這不僅意味著可以動態(tài)地生成方法,也意味著可以在運行時 按需 生成方法。 跟其他動態(tài)語言一樣,Lua 提供了一個方法,允許程序員在找不到對應(yīng)方法時調(diào)用特定的處理邏輯,那就是 __index。

__index 在前面的元表一章中已經(jīng)介紹過了。跟“給表中的鍵附上默認(rèn)值”類似,我們也可以給模塊中的方法名附上默認(rèn)實現(xiàn)。 所需的只是如下的代碼:

setmetatable(_M, {__index = function(self, cmd)
    local method =
        function (self, ...)
            return call(self, cmd, ...)
        end

    -- cache the lazily generated method in our
    -- module table
    _M[cmd] = method
    return method
end})

現(xiàn)在我們可以不用準(zhǔn)備一份超長的命令列表,也無需為用不到的命令付生成方法的開銷,同時給未來的命令也留好了位置。 一切魔法均隱藏于代碼之中,may the source be with you!