1. 對比Lua腳本方案與Redis自身事務
對比表格
對比維度 | Redis事務(MULTI/EXEC) | Lua腳本方案 |
---|---|---|
原子性 | 事務命令序列化執行,但中間可被其他命令打斷,不保證原子性 | Lua腳本在Redis單線程中原子執行,不可中斷 |
計算能力 | 僅支持Redis內置命令,無法復雜計算 | 支持Lua腳本,可實現復雜邏輯運算 |
性能 | 需多次網絡交互,性能較低 | 通過SHA1復用腳本,減少網絡傳輸,性能更高 |
適用場景 | 簡單命令序列化執行 | 需要原子性且涉及復雜計算的場景 |
2. 兩種運行Lua腳本的方法示例
方法1:直接發送Lua腳本(不緩存)
-- Lua腳本:將key1的值加1,并返回新值
local value = tonumber(redis.call('GET', KEYS[1]))
redis.call('SET', KEYS[1], value + 1)
return value + 1
Java代碼:
// 直接執行Lua腳本,每次傳遞腳本內容
RedisScript<Long> script = new DefaultRedisScript<>( "local v=tonumber(redis.call('GET', KEYS[1])); " + "redis.call('SET', KEYS[1], v+1); return v+1", Long.class);
Long result = redisTemplate.execute( script, Arrays.asList("key1"), new Object[]{});
方法2:先緩存SHA1后調用
-- 先執行以下腳本緩存到Redis
// 第一次執行時緩存腳本
String script = "...(同上)...";
String sha1 = redisTemplate.execute(new DefaultRedisScript<>(script, Object.class)).getSha(); // 獲取SHA1 // 后續調用時僅傳SHA1和參數
redisTemplate.execute( new DefaultRedisScript<Long>(sha1, Long.class), Arrays.asList("key1"), new Object[]{});
3. RedisScript接口及子類詳解
RedisScript接口方法說明
方法名 | 作用描述 |
---|---|
getSha() | 返回腳本的SHA1哈希值(若已緩存) |
getArgsCount() | 返回腳本需要的參數數量 |
getNumberParams() | 是否需要參數(已廢棄,建議用getArgsCount() ) |
getBody() | 返回腳本的原始內容(若未緩存) |
DefaultRedisScript類
-
構造方法:
new DefaultRedisScript<>(scriptContent, returnType); // 傳入腳本內容 new DefaultRedisScript<>(sha1, returnType); // 傳入SHA1
-
關鍵方法:
// 設置腳本內容 script.setScriptText("lua script content"); // 設置SHA1(需確保腳本已緩存) script.setSha("computed_sha1"); // 設置參數數量 script.setArgsCount(2);
4. RedisTemplate的execute()方法對比
方法1:默認序列化器
// 使用默認序列化器(如StringRedisSerializer)
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) { ... } // 示例:執行計數器腳本
RedisScript<Long> script = new DefaultRedisScript<>( "return tonumber(redis.call('INCR', KEYS[1]))", Long.class);
Long result = redisTemplate.execute( script, Arrays.asList("counter_key"), new Object[]{});
方法2:自定義序列化器
// 自定義參數和結果的序列化方式
public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer, List<K> keys, Object... args) { ... } // 示例:處理JSON參數和結果
RedisScript<MyObject> script = ...;
MyObject result = redisTemplate.execute( script, Jackson2JsonRedisSerializer.class, // 參數序列化器 new Jackson2JsonRedisSerializer<>(MyObject.class), // 結果序列化器 Arrays.asList("key"), new MyParamObject() // 自定義參數對象
);
對比表格
方法版本 | 參數序列化器 | 結果序列化器 | 適用場景 |
---|---|---|---|
默認方法 | 使用RedisTemplate默認配置 | 使用RedisTemplate默認配置 | 簡單類型(如String、Long) |
自定義方法 | 可指定任意RedisSerializer | 可指定任意RedisSerializer | 復雜對象(如JSON、POJO) |