一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - Redis - redis執行lua腳本的實現方法

redis執行lua腳本的實現方法

2022-01-19 18:12當編程已成習慣 Redis

redis在2.6推出了腳本功能,允許開發者使用Lua語言編寫腳本傳到redis中執行。本文就介紹了redis執行lua腳本的實現方法,感興趣的可以了解一下

從redis 2.6.0版本開始,redis內置了lua解釋器,并提供了eval命令來解析lua腳本求值。

1. 語法格式

語法: eval script numkeys keys args

參數: eval — redis提供解析lua腳本的命令

         script — lua腳本

          numkeys — 指定鍵名參數集(keys)的個數

          keys — 鍵名參數集,通過全局變量keys數組表示,起始下標為1

          args — 鍵值參數集,通過全局變量argv數組表示,起始下標為1

描述:  eval命令的語義要求字面量不要直接寫在lua腳本中,推薦使用變量來定義lua腳本,并將字面量放在鍵名參數集keys和鍵值參數集args中,通過全局變量keys和argv來獲取,這樣做的好處是可緩存!在lua腳本中,可以使用兩個函數來執行redis命令,分別是:redis.call()和redis.pcall()

例子:

?
1
2
3
4
## 第一個eval命令,設置一個key=name,value=sym的字符串
eval "return redis.call('set',keys[1],arga[1])" 1 name sym
## 第二個eval命令:獲取key=name的字符串的值
eval "return redis.call('get',keys[1])" 1 name

redis執行lua腳本的實現方法

錯誤處理:

上面說過,在lua腳本中可以使用call()和pcall()來執行redis腳本,這兩個函數的效果是一模一樣的,唯一區別就是它們對于錯誤處理的不同:

①redis.call()在執行命令中發生錯誤,腳本會停止執行,返回一個腳本錯誤,錯誤的輸出信息會說明錯誤造成的原因:

redis執行lua腳本的實現方法

②redis.pcall()執行命令出錯時將捕獲錯誤并返回表示錯誤的lua表類型

redis執行lua腳本的實現方法

2.類型轉換

當 lua 通過 call() 或 pcall() 函數執行 redis 命令的時候,命令的返回值會被轉換成 lua 數據結構;同樣地,當lua腳本在 redis內置解釋器里運行時,lua的返回值也會被轉換成redis類型,然后由eval將值返回客戶端。lua類型與redis類型之間存在一一轉換的關系:

redis -> lua

 

redis類型

lua類型

描述

redis_integer

lua_number

redis整數轉為lua數字

redis_bulk

lua_string

redis bulk回復轉為lua字符串

redis_multi bulk

lua_table

redis 多條bulk回復轉為lua 表

redis_status

lua_table

redis狀態回復轉為lua表,表內ok域包含狀態信息

redis_error

lua_table

redis錯誤回復轉為lua表,表內的err域包含錯誤信息

redis_nil、

redis_multi nil

lua_boolean_false

redis的nil回復和nil多條回復轉為lua的布爾值false

 

lua -> redis

 

lua類型

redis類型

描述

lua_number

redis_integer

lua數字轉為redis整數

lua_string

redis_bluk

lua字符串轉為redis bulk回復

lua_table、

lua_array

redis_multi bulk

lua表(數組)轉為redis多條bulk回復

lua_table_ok

redis status

一個帶單個ok域的lua表,轉為redis

狀態回復

lua_table_err

redis_error

一個帶單個err域的lua表,轉為redis

錯誤回復

lua_boolean_false

redis nil

lua布爾值false轉為redis的nil回復

 

從lua轉換到redis有一條額外的規則,這條規則沒有與其相對應的redis轉換為lua的規則:

lua_boolean_true -> redis_integer_1,lua布爾值true轉為redis整數1

redis執行lua腳本的實現方法

3.lua腳本

3.1 script命令

redis提供了以下幾個script命令,用于對于腳本子系統進行控制:

script flush:清除所有的腳本緩存

script load:將腳本裝入腳本緩存,不立即運行并返回其校驗和

script exists:根據指定腳本校驗和,檢查腳本是否存在于緩存

script kill:殺死當前正在運行的腳本(防止腳本運行緩存,占用內存)

redis執行lua腳本的實現方法

3.2 腳本原子性

redis使用單個lua解釋器去運行所有腳本,并且保證腳本會以原子性的方式去執行,意味著當某個腳本在運行時,不會有其它腳本或者redis命令被執行!所以,如果當前腳本運行很慢,服務器可能會因為正忙而無法執行命令,如:

redis執行lua腳本的實現方法

redis執行lua腳本的實現方法

每個腳本都有一個最大執行時間限制,默認值是5s。最大執行時間的長短由配置文件redis.conf的lua-time-limit選項來控制,或直接使用config get和config set命令來修改。當一個腳本執行達到最大執行時間,redis不會主動結束它,它會進行下面幾個步驟:

①redis記錄一個腳本正在超時運行

②redis開始重新接受其它客戶端請求,但只接受執行script kill命令和shutdown nosave兩個命令,若客戶端執行其它命令,redis會返回busy錯誤。

③如果腳本只執行過讀操作,使用script kill命令可以立即停止此腳本;如果腳本執行過寫操作,只允許shutdown save/nosave命令,通過停止服務器來阻止當前數據寫入磁盤。(此時服務器關閉,數據不會被保存)

  redis執行lua腳本的實現方法

3.3 腳本緩存和evalsha

redis有一個內部的腳本緩存機制,它不會每次都重新編譯腳本,反倒是它會將所有運行過的腳本永久保存在腳本緩存中(因為redis發現腳本體積非常小,即使量很大,甚至經常修改,儲存這些腳本的內存也是微不足道的)。清空腳本緩存只有唯一一個方式,就是執行script flush命令。使用eval命令執行腳本時,每次都要發送腳本主體,如果腳本足夠復雜,這會付出無謂的網絡帶寬。redis基于對lua的緩存,它實現了evalsha命令。

evalsha命令和eval命令效果一樣,都是解釋lua腳本執行,但是evalsha命令的第一個參數不是腳本主體,而是腳本的shai校驗和,這個校驗和可以通過script load命令得到。evalsha命令執行過程分兩步:

①如果redis服務器保存了給定sha1校驗和所指定的腳本,就會執行該腳本

②如果redis服務器沒保存給定sha1校驗和所指定的腳本,它就會返回一個特殊錯誤,告知客戶端使用eval命令去執行

如下圖所示:

  redis執行lua腳本的實現方法

3.4 全局變量保護

redis的lua腳本不允許創建全局變量,如果腳本需要在多次執行之間維持某種狀態,可以借助外部redis key來保存狀態,每次腳本執行前,獲取redis相對應的key賦值給局部變量。在lua腳本中創建或訪問一個全局變量,都會引起腳本停止,eval命令會返回一個錯誤:

redis執行lua腳本的實現方法

redis的全局變量保護并不是百分百成功,有時候會在腳本中混入lua全局狀態,可能會引發aof持久化和主從復制都無法得到保證。redis建議不要在腳本中使用全局變量,可以使用local關鍵字定義腳本中的變量!

redis執行lua腳本的實現方法

3.5 日志記錄

在redis中使用腳本不會自動記錄日志,需要我們在腳本使用redis.log()手動保存日志信息。腳本保存的日志,只有那些與redis實例所設置的日志等級相同或更高級才會被記錄。語法:redis.log(loglevel,message)。其中,message表示要記錄的日志信息,是一個字符串;loglevel表示redis日志等級,有4個取值:

   redis.log_debug

   redis.log_verbose

   redis.log_notice

   redis.log_warning

到此這篇關于redis執行lua腳本的實現方法的文章就介紹到這了,更多相關redis執行lua內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/sym542569199/article/details/88746776

延伸 · 閱讀

精彩推薦
  • RedisRedis 事務知識點相關總結

    Redis 事務知識點相關總結

    這篇文章主要介紹了Redis 事務相關總結,幫助大家更好的理解和學習使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • Redisredis實現排行榜功能

    redis實現排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實現排行榜功能,本文就來簡單的介紹一下如何使用,具有一定的參考價值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • RedisRedis的配置、啟動、操作和關閉方法

    Redis的配置、啟動、操作和關閉方法

    今天小編就為大家分享一篇Redis的配置、啟動、操作和關閉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡5312019-11-14
  • Redis詳解Redis復制原理

    詳解Redis復制原理

    與大多數db一樣,Redis也提供了復制機制,以滿足故障恢復和負載均衡等需求。復制也是Redis高可用的基礎,哨兵和集群都是建立在復制基礎上實現高可用的...

    李留廣10222021-08-09
  • RedisRedis如何實現數據庫讀寫分離詳解

    Redis如何實現數據庫讀寫分離詳解

    Redis的主從架構,能幫助我們實現讀多,寫少的情況,下面這篇文章主要給大家介紹了關于Redis如何實現數據庫讀寫分離的相關資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友...

    xiaojin21cen10152021-07-27
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    這篇文章主要給大家介紹了關于redis中如何使用lua腳本讓你的靈活性提高5個逼格的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具...

    一線碼農5812019-11-18
  • RedisRedis全量復制與部分復制示例詳解

    Redis全量復制與部分復制示例詳解

    這篇文章主要給大家介紹了關于Redis全量復制與部分復制的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Redis爬蟲具有一定的參考學習...

    豆子先生5052019-11-27
主站蜘蛛池模板: a4yy欧美一区二区三区 | 美女露全身永久免费网站 | 无颜之月全集免费观看 | 999国产精品亚洲77777 | 狠狠做五月深爱婷婷天天综合 | 亚洲欧美日韩特级毛片 | 人妖欧美一区二区三区四区 | 国产综合欧美日韩视频一区 | 国产成人亚洲精品91专区高清 | 91免费播放人人爽人人快乐 | 日本黄色大片网站 | 欧美男女爱爱视频 | 天美影视文化传媒mv免费 | 亚洲区在线播放 | 欧美一区二区三区免费不卡 | 唯美清纯 自拍偷 | 爆操美女在线观看 | 国产精品3p视频 | 岛国不卡 | 欧美在线一级片 | 九九精品国产亚洲A片无码 九九99热久久999精品 | 亚洲天堂色视频 | 精品无人乱码一区二区三区 | 青青青久热国产精品视频 | 青草悠悠视频在线观看 | 催眠白丝舞蹈老师小说 | 亚洲成年男人的天堂网 | 按摩院已婚妇女中文字幕 | 日本妇人成熟免费不卡片 | 都市后宫小说 | fuqer日本老师| 学校女性奴sm训练调教 | 日产国产精品亚洲系列 | 成人免费网址 | 91影视在线看免费观看 | 欧美成人一区二区 | 二次元美女扒开内裤露尿口 | 无人在线观看免费高清视频播放 | 日日夜夜撸影院 | 女人和男人搞基 | 日本国产成人精品视频 |