日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

openresty开发系列26--openresty中使用redis模块

發布時間:2025/3/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 openresty开发系列26--openresty中使用redis模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

openresty開發系列26--openresty中使用redis模塊

在一些高并發的場景中,我們常常會用到緩存技術,現在我們常用的分布式緩存redis是最知名的,

操作redis,我們需要引入redis模塊 require "resty.redis";

我們現在做個可以操作redis進行賦值,讀值的案例

一)連接redis服務器

---定義 redis關閉連接的方法
local function close_redis(red) ?
??? if not red then ?
??????? return ?
??? end ?
??? local ok, err = red:close() ?
??? if not ok then ?
??????? ngx.say("close redis error : ", err) ?
??? end ?
end ?

local redis = require "resty.redis"? --引入redis模塊
local red = redis:new()? --創建一個對象,注意是用冒號調用的
--設置超時(毫秒) ?
red:set_timeout(1000)
--建立連接 ?
local ip = "10.11.0.215" ?
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then ?
??? ngx.say("connect to redis error : ", err) ?
??? return close_redis(red) ?
end ?
--調用API設置key ?
ok, err = red:set("msg", "hello world") ?
if not ok then ?
??? ngx.say("set msg error : ", err) ?
??? return close_redis(red) ?
end ?
--調用API獲取key值 ?
local resp, err = red:get("msg") ?
if not resp then ?
??? ngx.say("get msg error : ", err) ?
??? return close_redis(red) ?
end

ngx.say("msg : ", resp)
close_redis(red) ?

請求結果?? msg : hello world

--------------------------------
注意:得到的數據為空處理 ,redis返回的空 為null,所以不能用nil判斷,而要用ngx.null判斷
if resp == ngx.null then ?
??? resp = ''? --比如默認值 ?
end ?


--------------連接授權的redis-----------------
在redis.conf配置文件 配置認證密碼
requirepass redis123

注意:windows 啟動redis時,配置redis.windows.conf;并且不能直接 雙擊redis-server.exe,
如果雙擊啟動,默認不會找此目錄下的配置文件;需要指定配置文件
解決方案:
1)cmd窗口中 運行 redis-server.exe redis.windows.conf
2)新建一個bat批處理文件? 文件內容 redis-server.exe redis.windows.conf


連接報錯set msg error : NOAUTH Authentication required.因為認證出錯
在red:connect成功后,調用red:auth認證密碼

ok, err = red:auth("redis123")
if not ok then
?? ?ngx.say("failed to auth: ", err)
?? ?return close_redis(red)
end


二)redis連接池

redis的連接是tcp連接,建立TCP連接需要三次握手,而釋放TCP連接需要四次握手,而這些往返時延僅需要一次,
以后應該復用TCP連接,此時就可以考慮使用連接池,即連接池可以復用連接。
我們需要把close_redis函數改造一下

local function close_redis(red) ?
??? if not red then ?
??????? return ?
??? end ?
??? --釋放連接(連接池實現) ?
??? local pool_max_idle_time = 10000 --毫秒 ?
??? local pool_size = 100 --連接池大小 ?
??? local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) ?
??? if not ok then ?
??????? ngx.say("set keepalive error : ", err) ?
??? end
end

即設置空閑連接超時時間防止連接一直占用不釋放;設置連接池大小來復用連接。
注意:
1、連接池是每Worker進程的,而不是每Server的;
2、當連接超過最大連接池大小時,會按照LRU算法回收空閑連接為新連接使用;
3、連接池中的空閑連接出現異常時會自動被移除;
4、連接池是通過ip和port標識的,即相同的ip和port會使用同一個連接池(即使是不同類型的客戶端);
5、連接池第一次set_keepalive時連接池大小就確定下了,不會再變更;

注意:我們如何知道,redis連接對象是從連接池中獲取的,還是新創建的連接呢??

使用 red:get_reused_times --->得到此連接被使用的次數

如果當前連接不是從內建連接池中獲取的,該方法總是返回 0 ,也就是說,該連接還沒有被使用過。

如果連接來自連接池,那么返回值永遠都是非零。所以這個方法可以用來確認當前連接是否來自池子。



連接優化

采用連接池,連接帶認證的redis

---定義 redis關閉連接的方法
local function close_redis(red) ?
??? if not red then ?
??????? return ?
??? end ?
??? --釋放連接(連接池實現) ?
??? local pool_max_idle_time = 10000 --毫秒 ?
??? local pool_size = 100 --連接池大小 ?
??? local ok, err = red:set_keepalive(pool_max_idle_time, pool_size) ?
??? if not ok then ?
??????? ngx.say("set keepalive error : ", err) ?
??? end ?
end? ?

local redis = require "resty.redis"? --引入redis模塊
local red = redis:new()? --創建一個對象,注意是用冒號調用的
--設置超時(毫秒) ?
red:set_timeout(1000)
--建立連接 ?
local ip = "10.11.0.215" ?
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then ?
??? ngx.say("connect to redis error : ", err) ?
??? return close_redis(red) ?
end ?

local count, err = red:get_reused_times()
if 0 == count then ----新建連接,需要認證密碼
?? ?ok, err = red:auth("redis123")
?? ?if not ok then
?? ??? ?ngx.say("failed to auth: ", err)
?? ??? ?return
?? ?end
elseif err then? ----從連接池中獲取連接,無需再次認證密碼
?? ?ngx.say("failed to get reused times: ", err)
?? ?return
end

--調用API設置key ?
ok, err = red:set("msg", "hello world333333333") ?
if not ok then ?
??? ngx.say("set msg error : ", err) ?
??? return close_redis(red) ?
end ?
--調用API獲取key值 ?
local resp, err = red:get("msg") ?
if not resp then ?
??? ngx.say("get msg error : ", err) ?
??? return close_redis(red) ?
end

ngx.say("msg : ", resp)
close_redis(red)

=======================================

注意:連接池使用過程中,業務代碼有select方法,會導致數據錯亂

ok, err = red:select(1)? --->選擇db
if not ok then
??? ngx.say("failed to select db: ", err)
??? return
end

如:
A業務使用了db1,所以使用了 select(1);

B業務使用默認的db0,select(0)遺漏

但A,B業務共用了連接池,很有可能 B業務拿到的 A業務使用的連接,而此連接操作的數據庫db1;
而B業務中代碼沒有指定select數據庫,所以B業務操作數據到了db1中;導致數據錯亂

轉載于:https://www.cnblogs.com/reblue520/p/11434278.html

總結

以上是生活随笔為你收集整理的openresty开发系列26--openresty中使用redis模块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。