在高并發(fā)系統(tǒng)中株茶,redis的使用會(huì)比較頻繁,lua腳本讓redis的使用更加靈活图焰。
redis中使用lua腳本的好處總結(jié)為:
- 原子性操作:lua腳本在執(zhí)行的過程中是一個(gè)事務(wù)進(jìn)行提交启盛;
- 減少網(wǎng)絡(luò)開銷:執(zhí)行l(wèi)ua可以將多個(gè)請(qǐng)求一次發(fā)到redis中減少網(wǎng)絡(luò)的開銷;
- 腳本復(fù)用:客戶端可以將lua腳本永遠(yuǎn)保存在redis中技羔,以達(dá)到腳本的復(fù)用僵闯;
但是,由于redis是單線程-多路復(fù)用IO模型藤滥,所以在redis中執(zhí)行l(wèi)ua是否會(huì)有阻塞鳖粟,
下面寫個(gè)腳本簡單測試一下:
redis單機(jī)模式:
- 簡單寫個(gè)循環(huán)加法的lua腳本阻塞redis,執(zhí)行如下:
shifeiyandeMacBook-Pro:~ shifeiyan$ ./redis-cli
127.0.0.1:6379> keys *
1) "lme"
2) "lme0225"
3) "expire0"
4) "txn"
127.0.0.1:6379> eval "local a=redis.call('hget','lme0225','margin1') local b=1 repeat b=b+1 until(b>100000000000000) return a" 0
- 再開一個(gè)終端查看一下所有的key值:
shifeiyandeMacBook-Pro:~ shifeiyan$ ./redis-cli
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
127.0.0.1:6379>
結(jié)論
執(zhí)行l(wèi)ua 會(huì)阻塞整個(gè)redis實(shí)例中所有的緩存信息超陆,即 不能對(duì)緩存有任何操作牺弹,否則會(huì)報(bào)BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
redis集群模式
集群說明:redis集群測試環(huán)境為三主三從的集群環(huán)境
測試步驟如下:
- 用同單機(jī)一樣的方法執(zhí)行l(wèi)ua腳本;
-
查看集群信息如下:
-
重新打開一個(gè)終端时呀,連接這在阻塞的redis實(shí)例张漂,看集群下是否會(huì)阻塞如下:
-
再開一個(gè)命令窗口,連接集群中當(dāng)前被阻塞的redis主機(jī)的從機(jī)谨娜,進(jìn)行操作如下:
-
再開一個(gè)終端航攒,連接到集群中非阻塞的主機(jī)redis中,進(jìn)行操作:
-
在上面打開的終端中趴梢,查看改主機(jī)redis中的key如下:
-
kill掉正在執(zhí)行的lua腳本如下:
結(jié)論:
- 單臺(tái)機(jī)阻塞漠畜,會(huì)影響集群中一主一從中的緩存操作币他,因?yàn)閞edis集群下操作的是主機(jī),所以連接到從機(jī)操作緩存憔狞,也會(huì)重定向到到對(duì)應(yīng)的主機(jī)中蝴悉,從機(jī)可以查看所有的key,但是不能進(jìn)行操作瘾敢;
- 不會(huì)影響集群中非阻塞redis實(shí)例中的緩存操作拍冠,包括lua腳本的執(zhí)行;
- 連接到被阻塞的實(shí)例簇抵,操作非阻塞實(shí)例中的緩存不會(huì)有影響庆杜,即可以重定向到其他主機(jī)實(shí)例進(jìn)行緩存操作;
以上測試 在lua腳本中只是操作了集群中單臺(tái)redis中的緩存碟摆,然后還分別寫了一個(gè)操作兩臺(tái)redis實(shí)例三臺(tái)redis實(shí)例中緩存的lua腳本晃财,分別進(jìn)行阻塞,使用簡單的命令進(jìn)行測試典蜕,結(jié)果顯示:會(huì)阻塞集群中二主二從断盛,三主三從redis實(shí)例;