當前位置:首頁 » 編程軟體 » redis腳本操作

redis腳本操作

發布時間: 2022-12-20 09:17:55

1. redis有腳本語言嗎

有,lua腳本語言

Redis腳本

使用腳本的好處:

  • 減少網路開銷。可以將多個請求通過腳本的形式一次發送,減少網路時延

  • 原子操作。redis會將整個腳本作為一個整體執行,中間不會被其他命令插入。因此在編寫腳本的過程中無需擔心會出現競態條件,無需使用事務。

  • 復用。客戶端發送的腳步會永久存在redis中,這樣,其他客戶端可以復用這一腳本而不需要使用代碼完成相同的邏輯。

  • 調用Lua腳本的語法:

    $ redis-cli --eval path/to/redis.lua KEYS[1] KEYS[2] , ARGV[1] ARGV[2] ...

  • --eval,告訴redis-cli讀取並運行後面的lua腳本

  • path/to/redis.lua,是lua腳本的位置

  • KEYS[1] KEYS[2],是要操作的鍵,可以指定多個,在lua腳本中通過KEYS[1], KEYS[2]獲取

  • ARGV[1] ARGV[2],參數,在lua腳本中通過ARGV[1], ARGV[2]獲取。

  • 注意:

    KEYS和ARGV中間的 ',' 兩邊的空格,不能省略。

    redis支持大部分Lua標准庫

    庫名

    說明

    Base 提供一些基礎函數

    String 提供用於字元串操作的函數

    Table 提供用於表操作的函數

    Math 提供數學計算函數

    Debug 提供用於調試的函數

    在腳本中調用redis命令

    在腳本中可以使用redis.call函數調用Redis命令

  • redis.call('set', 'foo', 'bar')local value=redis.call('get', 'foo') --value的值為bar

  • redis.call函數的返回值就是Redis命令的執行結果

    Redis命令的返回值有5種類型,redis.call函數會將這5種類型的回復轉換成對應的Lua的數據類型,具體的對應規則如下(空結果比較特殊,其對應Lua的false)

    redis返回值類型和Lua數據類型轉換規則

    redis返回值類型

    Lua數據類型

    整數回復 數字類型

    字元串回復 字元串類型

    多行字元串回復 table類型(數組形式)

    狀態回復 table類型(只有一個ok欄位存儲狀態信息)

    錯誤回復 table類型(只有一個err欄位存儲錯誤信息)

    redis還提供了redis.pcall函數,功能與redis.call相同,唯一的區別是當命令執行出錯時,redis.pcall會記錄錯誤並繼續執行,而redis.call會直接返回錯誤,不會繼續執行。

    在腳本中可以使用return語句將值返回給客戶端,如果沒有執行return語句則默認返回nil

    Lua數據類型和redis返回值類型轉換規則

    Lua數據類型

    redis返回值類型

    數字類型 整數回復(Lua的數字類型會被自動轉換成整數)

    字元串類型 字元串回復

    table類型(數組形式) 多行字元串回復

    table類型(只有一個ok欄位存儲狀態信息) 狀態回復

    table類型(只有一個err欄位存儲錯誤信息) 錯誤回復

    腳本相關命令

  • EVAL "lua-script" [key ...] [arg ...]

    通過key和arg這兩類參數向腳本傳遞數據,它們的值在腳本中分別使用KEYS和ARGV兩個表類型的全局變數訪問

    注意: EVAL命令依據參數key-number來將其後面的所有參數分別存入腳本中KEYS和ARGV兩個table類型的全局變數。當腳本不需要任何參數時,也不能省略這個參數(設為0)

    redis>EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 foo bar
    OK
    redis>GET foo"bar"
  • EVALSHA命令

    在腳本比較長的情況下,如果每次調用腳本都需要將整個腳本傳給Redis會佔用較多的帶寬。為了解決這個問題,Redis提供了EVALSHA命令,允許開發者通過腳本內容的SHA1摘要來執行腳本,該命令的用法和EVAL一樣,只不過是將腳本內容替換成腳本內容的SHA1摘要。

    Redis在執行EVAL命令時會計算腳本的SHA1摘要並記錄在腳本緩存中,執行EVALSHA命令時Redis會根據提供的摘要從腳本緩存中查找對應的腳本內容,如果找到了則執行腳本,否則會返回錯誤:"NOSCRIPT No matching script. Please use EVAL."

    在程序中使用EVALSHA命令的一般流程如下。

    雖然這一流程略顯麻煩,但值得慶幸的是很多編程語言的Redis客戶端都會代替開發者完成這一流程。執行EVAL命令時,先嘗試執行EVALSHA命令,如果失敗了才會執行EVAL命令。

  • 先計算腳本的SHA1摘要,並使用EVALSHA命令執行腳本。

  • 獲得返回值,如果返回「NOSCRIPT」錯誤則使用EVAL命令重新執行腳本。

  • SCRIPTLOAD "lua-script"

    將腳本加入緩存,但不執行. 返回:腳本的SHA1摘要

  • SCRIPT EXISTS lua-script-sha1

    判斷腳本是否已被緩存

  • SCRIPT FLUSH

    清空腳本緩存 redis將腳本的SHA1摘要加入到腳本緩存後會永久保留,不會刪除,但可以手動使用SCRIPT FLUSH命令情況腳本緩存。

  • SCRIPT KILL

    強制終止當前腳本的執行。 但是,如果當前執行的腳步對redis的數據進行了寫操作,則SCRIPT KILL命令不會終止腳本的運行,以防止腳本只執行了一部分。腳本中的所有命令,要麼都執行,要麼都不執行。

  • Redis的腳本執行是原子的,即腳本執行期間Redis不會執行其他命令。所有的命令都必須等待腳本執行完成後才能執行。為了防止某個腳本執行時間過長導致Redis無法提供服務(比如陷入死循環),Redis提供了lua-time-limit參數限制腳本的最長運行時間,默認為5秒鍾。當腳本運行時間超過這一限制後,Redis將開始接受其他命令但不會執行(以確保腳本的原子性,因為此時腳本並沒有被終止),而是會返回「BUSY」錯誤

2. 如何使用SHELL編寫redis的啟動腳本

#!/bin/bash
#
# Init file for redis
# From: JC
# Email:[email protected]
# chkconfig: - 80 12
# description: redis daemon
#
# processname: redis
# config: /opt/redis-2.6.4/redis.conf
# pidfile: /var/run/redis.pid

source /etc/init.d/functions

BIN="/opt/redis/bin"
CONFIG="/opt/redis-2.6.4/redis.conf"
PIDFILE="/var/run/redis.pid"

### Read configuration
[ -r "$SYSCONFIG" ] && source "$SYSCONFIG"

RETVAL=0
prog="redis-server"
desc="Redis Server"

start() {

if [ -e $PIDFILE ];then
echo "$desc already running...."
exit 1
fi

echo -n $"Starting $desc: "
daemon $BIN/$prog $CONFIG &

RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
return $RETVAL
}

stop() {
echo -n $"Stop $desc: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog $PIDFILE
return $RETVAL
}

restart() {
stop
start
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart)
[ -e /var/lock/subsys/$prog ] && restart
RETVAL=$?
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
RETVAL=1
esac

exit $RETVAL

[root@dg-web opt]# /etc/init.d/redis status
redis-server (pid 26147) is running...
[root@dg-web opt]# netstat -lntp|grep redis-server
URL:http://www.bianceng.cn/database/MySQL/201410/46081.htm
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 26147/redis-server
[root@dg-web opt]# /etc/init.d/redis stop
Stop Redis Server: [ OK ]
[root@dg-web opt]# /etc/init.d/redis status
redis-server is stopped
[root@dg-web opt]# netstat -lntp|grep redis-server

3. Redis中使用Lua

在一些互聯網項目中,難免會設計到一些原子性操作,例如實時交易量的累加,分布式鎖的實現,那麼採用lua腳本可以幫助我們完成一個原子性的操作

Redis會使用相同的 Lua 解釋器來運行所有命令。Redis 還保證以原子方式執行腳本:在執行腳本時不會執行其他腳本或 Redis 命令。

使用Lua腳本的好處有

基本用法

例如

返回結果

使用Lua實現分布式鎖
加鎖

解鎖

4. 為什麼在 Redis 實現 Lua 腳本事務

1. 完成所有工作,所有寫操作處理完成後腳本會自動退出。
2. 腳本運行時出錯並中途退出,所有以前執行的寫操作都已發生,但不會再有其他寫操作。
3. Redis 通過 SHUTDOWN NOSAVE 關閉時(不保存)。
4. 你附加了調試器來「使」腳本完成 #1 與 #2 (或其他手段來保證不會丟失數據)。
對於使用資料庫開發軟體的人,我想你也認同只有情景 #1 是最理想的。情景 #2,#3,#4 都會導致數據異常(#2 與 #4)和/或數據丟失(#3 和 #4)。如果你很重視數據,你應該盡可能地阻止數據異常與丟失。這不是哲學,而是工作(This is not philosophy, this is doing your job)。但很遺憾目前的 Redis 也幫不了你多少。所以我決定改變這種情況。

5. 為什麼在 Redis 實現 Lua 腳本事務

數據完整性

從很多方面來看,Redis 很像當初採用 InnoDB 前的 MySQL。而 Redis 採用了一種很合理的方式來保證數據完整性(復制,AOF 等),並且從 Redis2.6 開始引入的 Lua 腳本在功能與易用性方面為 Redis 的成長提供了很大助力。

相對來說,Lua 腳本與其他資料庫中的存儲過程很相似,但腳本的執行有些許不同。在本文中最重要的一點就是一旦將腳本寫入資料庫,它會一直執行直到以下任一種情況出現:

1. 完成所有工作,所有寫操作處理完成後腳本會自動退出。

2. 腳本運行時出錯並中途退出,所有以前執行的寫操作都已發生,但不會再有其他寫操作。

3. Redis 通過 SHUTDOWN NOSAVE 關閉時(不保存)。

4. 你附加了調試器來「使」腳本完成 #1 與 #2 (或其他手段來保證不會丟失數據)。

對於使用資料庫開發軟體的人,我想你也認同只有情景 #1 是最理想的。情景 #2,#3,#4 都會導致數據異常(#2 與
#4)和/或數據丟失(#3 和 #4)。如果你很重視數據,你應該盡可能地阻止數據異常與丟失。這不是哲學,而是工作(This is not
philosophy, this is doing your job)。但很遺憾目前的 Redis 也幫不了你多少。所以我決定改變這種情況。

6. 為什麼在 Redis 實現 Lua 腳本事務

從很多方面來看,Redis 很像當初採用 InnoDB 前的 MySQL。而 Redis 採用了一種很合理的方式來保證數據完整性(復制,AOF 等),並且從 Redis2.6 開始引入的 Lua 腳本在功能與易用性方面為 Redis 的成長提供了很大助力。

相對來說,Lua 腳本與其他資料庫中的存儲過程很相似,但腳本的執行有些許不同。在本文中最重要的一點就是一旦將腳本寫入資料庫,它會一直執行直到以下任一種情況出現:

1. 完成所有工作,所有寫操作處理完成後腳本會自動退出。

2. 腳本運行時出錯並中途退出,所有以前執行的寫操作都已發生,但不會再有其他寫操作。

3. Redis 通過 SHUTDOWN NOSAVE 關閉時(不保存)。

4. 你附加了調試器來「使」腳本完成 #1 與 #2 (或其他手段來保證不會丟失數據)。

對於使用資料庫開發軟體的人,我想你也認同只有情景 #1 是最理想的。情景 #2,#3,#4 都會導致數據異常(#2 與
#4)和/或數據丟失(#3 和 #4)。如果你很重視數據,你應該盡可能地阻止數據異常與丟失。這不是哲學,而是工作(This is not
philosophy, this is doing your job)。但很遺憾目前的 Redis 也幫不了你多少。所以我決定改變這種情況。

7. (2)Redis常見功能分析

原理:

Redission已提供支持,無需重復造輪子。(通過Lua腳本實現)

分布式鎖需要考慮哪些問題。

Lua腳本是一種腳本語言,弱類型(靈活性較強)。在Redis中能夠保證原子性。主要通過阻塞方式實現。(如果有一個客戶端執行Lua腳本中,其他客戶端的操作將會提示Redis Busy),如果Lua腳本不涉及事務操作(修改、新增、刪除數據),那麼其他客戶端可以通過kill script 命令強制結束Lua腳本執行。如果涉及到事務,則只能重啟(丟棄上次快照之後的數據緩存)。

Redis在用Lua腳本保證原子性的同時,也承擔了額外的風險。因此使用Lua腳本時要注意,避免阻塞。另外Redis Config中也包含對Lua腳本超時時間的設置,可以根據實際情況靈活的配置使用。

Lua 腳本也可以壓縮緩存,生成hash返回,後續使用Hash調用。

時間輪,主要用來管理延遲任務執行(kafka的實現也是基於時間輪)

8. lua腳本~ Redis調用

參考資料:

redis常見命令

官方調用lua文檔

redis菜鳥教程

lua菜鳥教程

其他:

https://www.cnblogs.com/kaituorensheng/p/11098194.html

https://blog.csdn.net/z69183787/article/details/80266417

一句話,因為要用所以學習簡單粗暴

本次僅學習如何使用redis調用lua腳本(含springboot調用方式),lua腳本如何寫以後有時間在玩。

寫redis鎖時經常使用的一個腳本:

我這里的客戶端用的 windows 的,將准備好的 lua 腳本放在自己指定的文件夾

報錯了!!! why ??? 這個符合eval語法吖?

其實,這裡面有一個問題就是如果想要直接執行文件,就不需要進入 redis-client

當然如果想要在 reids-client 內執行怎麼辦呢?

這里展示部分代碼

將腳本放在 resouces 文件下 lua/unlock.lua

測試代碼:

測試控制台結果。當然也需要在redis-client中檢查下是否是正確的結果

9. Redis 中使用 Lua 腳本

Redis 本身已經提供了豐富的命令,但是直接用來處理一些復雜業務時可能還不夠方便,會有一定的局限性。因此,在 Redis2.6 版本開始提供了對 Lua 腳本的支持,Lua 腳本的使用還是比較廣泛的,比如商品秒殺、分布式鎖等,使用 Lua 腳本可以帶來以下的好處:

為了讓例子更加的貼近實際應用,這里實現一個簡單版的分布式鎖。這里先用 Jedis 操作。

上邊詳細的介紹了分布式鎖的實現過程,以及可能出現的問題,最終,我們決定刪除鎖的操作使用 Lua 腳本實現,對應的腳本如下:

Lua 腳本中執行具體的 Redis 命令,需要使用 redis.call() 方法, KEYS 表示客戶端發起腳本執行命令時攜帶的 Redis key 的一個集合, ARGV 則是其它參數的一個集合,主意下標從1開始。結合我們的業務,這里的 KEYS[1] 則表示 lock , ARGV[1] 則是一個隨機字元串。整個腳本的含義就是,如果客戶端傳遞的 lock 的 value 和 Redis 中存儲的一致,就刪除 lock 。

Lua 腳本的語法還是比較簡單的,具體內容可以自行學習。

前邊的准備工作基本結束了,文章開始說過執行腳本有兩種途徑,下邊我們具體來看:

這里使用 jedis.eval() 發送腳本到 Redis 伺服器執行,後兩個參數分別是 key 的集合,以及 value 參數的集合。

先將腳本以文件形式放到 Redis 里,例如這樣:

然後通過如下命令讓 Redis 伺服器緩存腳本:

script load 命令會在 Redis 伺服器緩存 Lua 腳本,並且腳本內容經過 SHA-1 簽名演算法處理後,會返回腳本內容的 SHA1 校驗和的編碼,然後在端調用時,傳入編碼字元串作為參數,這樣 Redis 伺服器就會執行對應緩存的腳本了,就不用了每次發送具體的腳本內容了。

還有兩個比較有用的命令:

除了使用上邊的命令緩存腳本、生成腳本的 SHA1 校驗和的編碼,還可以使用 Jedis 實現,但最終的 SHA1 編碼內容是不同的:

實際的項目中,可能更多的會在 SpringBoot 項目中整合 Redis,此時執行 Lua 腳本的基本流程如下:

核心的類就是 DefaultRedisScript ,它實現了 RedisScript 介面。 execute() 方法最後一個參數是可變類型的,用來傳遞多個 value 參數。初次執行 execute() 方法時,其內部會自動緩存 Lua 腳本到 Redis 伺服器;同時每次執行腳本時會根據腳本內容自動計算出對應的 SHA1 校驗和的編碼,去匹配、執行緩存的腳本。

具體的 SHA1 校驗和的編碼,可以在 execute() 方法執行後,使用 redisScript.getSha1() 查看。使用 SpringBoot 方式 執行 Lua 腳本生成的 SHA1 校驗和的編碼和前邊直接使用 Jedis 生成的一致。

無論用那種方式在 Redis 中使用 Lua 腳本,其中的原理都是類似的。

10. Redis | 第9章 Lua 腳本與排序《Redis設計與實現》

參考資料 :《Redis設計與實現 第二版》;

第三部分為獨立功能的實現,主要由以下模塊組成: 發布訂閱 事務 Lua 腳本 排序 二進制位數組 慢查詢日誌 監視器

本篇將介紹 Redis 的 Lua 腳本 排序 。Redis 從 2.6 版本開始可以使用一些命令操作 Lua 腳本,引入相關支持;Redis 的 SORT 命令可以對列表鍵、集合鍵或者有序集合鍵的值進行排序,SORT 命令的一些可選性能讓我們得到想要的排序;

與本章相關的 Redis 命令總結在下篇文章,歡迎點擊收藏,本篇將不再重復:

《Redis常用命令及示例總結(API)》 : https://www.jianshu.com/p/f8eb9afaa908



熱點內容
電腦配置低怎麼變得不卡 發布:2025-07-15 05:34:08 瀏覽:843
ios火影忍者手游腳本 發布:2025-07-15 05:31:34 瀏覽:82
iphone支付密碼忘了怎麼辦 發布:2025-07-15 05:30:55 瀏覽:775
c語言打開網頁 發布:2025-07-15 05:21:33 瀏覽:640
如何製作我的世界模組伺服器 發布:2025-07-15 05:21:33 瀏覽:903
phparray加 發布:2025-07-15 05:20:41 瀏覽:782
4000以內二手安卓機怎麼選 發布:2025-07-15 05:11:25 瀏覽:644
靜態編譯修復器 發布:2025-07-15 05:11:24 瀏覽:506
iphonexr的存儲空間 發布:2025-07-15 05:09:20 瀏覽:328
能緩存航海王 發布:2025-07-15 04:55:38 瀏覽:91