欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis中Lua腳本的使用和設(shè)置超時

 更新時間:2021年11月24日 15:20:44   作者:hhgfy  
本文將介紹Redis中Lua腳本的基本用法,以及腳本超時導(dǎo)致的問題和處理方式。文中通過示例代碼介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下

Redis提供了Lua腳本功能來讓用戶實現(xiàn)自己的原子命令,但也存在著風(fēng)險,編寫不當(dāng)?shù)哪_本可能阻塞線程導(dǎo)致整個Redis服務(wù)不可用。

本文將介紹Redis中Lua腳本的基本用法,以及腳本超時導(dǎo)致的問題和處理方式。

EVAL命令簡介

eval格式

Redis 提供了命令EVAL來執(zhí)行Lua腳本,格式如下

EVAL script numkeys key [key …] arg [arg …]

其中 script 是將要執(zhí)行的腳本內(nèi)容,至于后面的腳本參數(shù)部分與本文無關(guān),在此不做贅述。

特性

由于Redis對數(shù)據(jù)集單線程讀寫的特性,Lua腳本執(zhí)行時會阻塞所有對數(shù)據(jù)集的讀寫操作,這給它帶來了下面兩個特性:

  • 原子性:可以通過Lua腳本實現(xiàn)對數(shù)據(jù)集的原子讀寫操作,這和Redis的事務(wù)功能MULTI / EXEC類似
  • 長時間阻塞風(fēng)險:如果Lua腳本執(zhí)行時間過長,導(dǎo)致整個Redis不可用

執(zhí)行流程

eval "return 'hello world'" 0為例,腳本執(zhí)行步驟如下

定義腳本函數(shù)

執(zhí)行過的腳本可以根據(jù)hash值找到函數(shù)重新使用

Redis會根據(jù)傳入的腳本內(nèi)容生成函數(shù),函數(shù)名由 f_ + 腳本內(nèi)容的sha1摘要組成。

function f_5332031c6b470dc5a0dd9b4bf2030dea6d65de91()
	return 'hello world'
end

函數(shù)保存到 Lua_scripts字典,便于 evalsha使用

執(zhí)行腳本函數(shù)

  • 將KEYS和ARGV兩個參數(shù)數(shù)組傳入Lua執(zhí)行環(huán)境
  • 裝載超時處理鉤子
  • 執(zhí)行腳本
  • 移除超時鉤子
  • 結(jié)果保存到客戶端輸出緩沖區(qū),等待服務(wù)器將結(jié)果返回客戶端
  • Lua環(huán)境垃圾回收

關(guān)于腳本超時

介紹完EVAL命令,下面來關(guān)注Lua腳本長時間阻塞的風(fēng)險。

Redis的配置文件中提供了如下配置項來規(guī)定最大執(zhí)行時長

  • Lua-time-limit 5000 Lua腳本最大執(zhí)行時間,默認(rèn)5秒

但這里有個坑,當(dāng)一個腳本達(dá)到最大執(zhí)行時長的時候,Redis并不會強(qiáng)制停止腳本的運行,僅僅在日志里打印個警告,告知有腳本超時。

Lua slow script detected: still in execution after 5000 milliseconds. You can try killing the script using the SCRIPT KILL command. Script SHA1 is: 2531e4edc1a1e2a9bac3c52e99466f9ccabf12c0

為什么不能直接停掉呢?

因為 Redis 必須保證腳本執(zhí)行的原子性,中途停止可能導(dǎo)致內(nèi)存的數(shù)據(jù)集上只修改了部分?jǐn)?shù)據(jù)。

(只讀的腳本應(yīng)該是可以自動停的,沒自動停的原因我猜測是:腳本超時嚴(yán)重可以肯定出現(xiàn)了編碼錯誤,作者可能希望在測試中盡早發(fā)現(xiàn)這種問題,而不是靠自動停止導(dǎo)致bug被忽略?)

如果時長達(dá)到 Lua-time-limit 規(guī)定的最大執(zhí)行時間,Redis只會做這幾件事情:

日志記錄有腳本運行超時

開始允許接受其他客戶端請求,但僅限于 SCRIPT KILLSHUTDOWN NOSAVE 兩個命令

其他請求仍返回busy錯誤

SCRIPT KILL 命令

如果Lua只是讀取數(shù)據(jù)而沒做修改的話,執(zhí)行 SCRIPT KILL 就可以直接終止腳本執(zhí)行,不用擔(dān)心數(shù)據(jù)被修改。

但是,如果腳本已經(jīng)改寫了數(shù)據(jù)內(nèi)容,SCRIPT KILL將報出以下錯誤,因為它破壞數(shù)據(jù)集的內(nèi)容。

(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

SHUTDOWN NOSAVE 命令

如上所述,如果腳本已經(jīng)執(zhí)行了寫命令,SCRIPT KILL將無法執(zhí)行。那我們就只剩以下兩種選擇了:

  • 繼續(xù)等待腳本執(zhí)行完成
  • 使用 SHUTDOWN NOSAVE 來直接停掉 Redis,并避免臟數(shù)據(jù)持久化到磁盤

最后,不知道你有沒有疑問,從開始執(zhí)行腳本到 SHUTDOWN 之間的寫命令會把日志寫到AOF里嗎?Lua腳本中的命令什么時候會寫AOF里?

講道理,既然 Redis 為了不破壞腳本的原子性而不讓SCRIPT KILL執(zhí)行,那么腳本中寫命令的 “提交” 也應(yīng)當(dāng)是原子執(zhí)行的,而不是執(zhí)行一句就向AOF里寫一句。

“提交”:借用數(shù)據(jù)庫中 commit 的概念,這里指寫入AOF文件中

下面就來驗證這個猜測:

先執(zhí)行 tail -f appendonly.aof 實時查看AOF文件變化

再開一個redis-cli 命令行執(zhí)行一個內(nèi)容如下的Lua腳本

redis.call('set','a','aaaa') --先執(zhí)行寫命令
local count = 1 
while( 999999999 > count ) -- 阻塞幾秒
do  
   count = count+1   
end
127.0.0.1:6379> eval "redis.call('set','a','aaaa') local count = 1 while( 999999999 > count ) do  count = count+1   end" 0
(nil)
(8.65s)

現(xiàn)象是,腳本剛開始執(zhí)行,AOF文件毫無反應(yīng),一直等到8秒后腳本完成,命令才追加寫入到AOF中。

這就驗證了Redis腳本里的寫命令是等到執(zhí)行完成后再一次性寫入AOF的。

參考

Redis設(shè)計與實現(xiàn)

到此這篇關(guān)于Redis中Lua腳本的使用和設(shè)置超時 的文章就介紹到這了,更多相關(guān)Redis Lua 超時內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis?存儲對象信息用?Hash?和String的區(qū)別

    Redis?存儲對象信息用?Hash?和String的區(qū)別

    這篇文章主要介紹了Redis存儲對象信息用Hash和String的區(qū)別,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • Redis如何實現(xiàn)分布式鎖

    Redis如何實現(xiàn)分布式鎖

    相信大家對鎖已經(jīng)不陌生了,本文主要介紹了Redis如何實現(xiàn)分布式鎖,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用

    簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用

    這篇文章主要介紹了簡介Lua腳本與Redis數(shù)據(jù)庫的結(jié)合使用,Redis是基于主存的高性能數(shù)據(jù)庫,需要的朋友可以參考下
    2015-06-06
  • Redis RDB技術(shù)底層原理詳解

    Redis RDB技術(shù)底層原理詳解

    為了使Redis在重啟之后仍能保證數(shù)據(jù)不丟失,需要將數(shù)據(jù)從內(nèi)存中以某種形式同步到硬盤中,這一過程就是持久化,本文重點給大家介紹Redis RDB技術(shù)底層原理實現(xiàn)方法,一起看看吧
    2021-09-09
  • AOP?Redis自定義注解實現(xiàn)細(xì)粒度接口IP訪問限制

    AOP?Redis自定義注解實現(xiàn)細(xì)粒度接口IP訪問限制

    這篇文章主要為大家介紹了AOP?Redis自定義注解實現(xiàn)細(xì)粒度接口IP訪問限制,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • redis數(shù)據(jù)一致性之延時雙刪策略詳解

    redis數(shù)據(jù)一致性之延時雙刪策略詳解

    在使用redis時,需要保持redis和數(shù)據(jù)庫數(shù)據(jù)的一致性,最流行的解決方案之一就是延時雙刪策略,今天我們就來詳細(xì)刨析一下,需要的朋友可以參考下
    2023-09-09
  • 使用Redis實現(xiàn)用戶積分排行榜的教程

    使用Redis實現(xiàn)用戶積分排行榜的教程

    這篇文章主要介紹了使用Redis實現(xiàn)用戶積分排行榜的教程,包括一個用PHP腳本進(jìn)行操作的例子,需要的朋友可以參考下
    2015-04-04
  • Redis實現(xiàn)唯一計數(shù)的3種方法分享

    Redis實現(xiàn)唯一計數(shù)的3種方法分享

    這篇文章主要介紹了Redis實現(xiàn)唯一計數(shù)的3種方法分享,本文講解了基于SET、基于 bit、基于 HyperLogLog三種方法,需要的朋友可以參考下
    2015-03-03
  • 關(guān)于Redis網(wǎng)絡(luò)模型的源碼詳析

    關(guān)于Redis網(wǎng)絡(luò)模型的源碼詳析

    這篇文章主要給大家介紹了關(guān)于Redis網(wǎng)絡(luò)模型的源碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Linux、Windows下Redis的安裝即Redis的基本使用詳解

    Linux、Windows下Redis的安裝即Redis的基本使用詳解

    Redis是一個基于內(nèi)存的key-value結(jié)構(gòu)數(shù)據(jù)庫,Redis 是互聯(lián)網(wǎng)技術(shù)領(lǐng)域使用最為廣泛的存儲中間件,這篇文章主要介紹了Linux、Windows下Redis的安裝即Redis的基本使用詳解,需要的朋友可以參考下
    2022-09-09

最新評論