EVAL、EVALSHA命令
Redis
從2.6.0版本開始提供了eval
命令,通過內置的Lua
解釋器,可以讓用戶執行一段Lua
腳本並返回數據。因爲Redis
單線程模型的特點,可以保證多個命令的原子性
(因爲最近的項目纔想到用Lua),詳細的使用方法請移步官方文檔。
腳本性能
-
Redis
保證了腳本執行的原子性,所以在當前腳本沒執行完之前,別的命令和腳本都是等待狀態,所以一定要控制好腳本中的內容,防止出現需要消耗大量時間的內容(邏輯相對簡單)。
帶寬優化
- 爲了避免每次執行都重複的將
Lua
腳本內容發送,Redis
提供了evalsha
命令,只需要將Lua腳本內容的SHA1校驗和發送即可(evalsha 6b1bf486c81ceb7edf3c093f4c48582e38c0e791 0
)。 - Lua腳本中的
變量
(動態數據)請使用KEYS
和ARGV
獲取,如果把變量
放在腳本中,必然會導致每次的腳本內容都不同(SHA1),Redis緩存大量無用或者一次性的腳本內容。
Redis Cluster 或 阿里雲Redis集羣版使用注意事項
Redis從3.0開始支持了Cluster功能,之前使用eval
的時候可能沒什麼問題,但當切換成Cluster模式的時候,可能會出現一些問題:
- ERR Error running script (call to f_4a610f5543b3c3450220da7bd47825d3b6bffae8): @user_script:1: @user_script: 1: Lua script attempted to access a non local key in a cluster node
- ERR eval/evalsha command keys must be in same slot(阿里雲Redis集羣版)
上面的錯誤是因爲Redis要求單個Lua腳本操作的key必須在同一個節點上,但是Cluster會將數據自動分佈到不同的節點(虛擬的16384個slot,具體看官方文檔),阿里雲集羣版的官網其實也有對應說明:在Redis集羣版實例中,事務、腳本等命令要求所有的key必須在同一個slot中,如果不在同一個slot中將返回以下錯誤信息(:command keys must in same slot)
如何解決?
CLUSTER KEYSLOT key的文檔中提供瞭解決方法,你需要將把key中的一部分使用{}
包起來,redis將通過{}
中間的內容作爲計算slot的key,類似key1{mykey}
、key2{mykey}
這樣的都會存放到同一個slot中(缺點是不能平滑的過度老業務,需要修改原來使用的key,如果之前的key是統一管理的,也沒那麼麻煩)
思考
如果某個業務都通過key{mykey}
去儲存獲取內容,所有的操作都會hash到同一個slot,這個slot所在的節點壓力就會變大(不均衡),如果解決?歡迎留言討論~