Kaynağa Gözat

新增批量设置Redis Key工具方法

woody 1 yıl önce
ebeveyn
işleme
6e1f41f767

+ 38 - 0
framework-redis/src/main/java/com/chelvc/framework/redis/util/RedisUtils.java

@@ -13,6 +13,7 @@ import java.util.UUID;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.function.Executor;
@@ -156,6 +157,13 @@ public class RedisUtils implements ApplicationContextAware {
                     "else redis.call('SETEX', KEYS[1], ARGV[3], ARGV[2]) " +
                     "return redis.call('DECRBY', KEYS[1], ARGV[1]) end";
 
+    /**
+     * Redis批量设值脚本(如果Key已存在则忽略)
+     */
+    private static final String SETNX_WITH_DURATION_SCRIPT =
+            "local success = {} for i = 1, #KEYS do if redis.call('SET', KEYS[i], ARGV[i], 'EX', ARGV[#ARGV], 'NX') " +
+                    "then table.insert(success, i - 1) end end return success";
+
     /**
      * Redis批量设值脚本(如果成功则更新过期时间)
      */
@@ -652,6 +660,36 @@ public class RedisUtils implements ApplicationContextAware {
         return template.execute(script, Collections.singletonList(key), initialValue, duration.getSeconds());
     }
 
+    /**
+     * 批量设置带过期时间的值,如果Key已存在则忽略
+     *
+     * @param template Redis操作模版实例
+     * @param mapping  键/值映射表
+     * @param duration 有效时间
+     * @return 设置成功Key列表
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static List<String> setnx(@NonNull RedisTemplate<String, ?> template, @NonNull Map<String, ?> mapping,
+                                     @NonNull Duration duration) {
+        if (CollectionUtils.isEmpty(mapping)) {
+            return Collections.emptyList();
+        }
+        int i = 0;
+        List<String> keys = Lists.newArrayListWithCapacity(mapping.size());
+        Object[] values = new Object[mapping.size() + 1];
+        for (Map.Entry<String, ?> entry : mapping.entrySet()) {
+            keys.add(entry.getKey());
+            values[i++] = entry.getValue();
+        }
+        values[i] = duration.getSeconds();
+        RedisScript<List> script = new DefaultRedisScript<>(SETNX_WITH_DURATION_SCRIPT, List.class);
+        List<Number> success = template.execute(script, keys, values);
+        if (CollectionUtils.isEmpty(success)) {
+            return Collections.emptyList();
+        }
+        return success.stream().map(Number::intValue).map(keys::get).collect(Collectors.toList());
+    }
+
     /**
      * 批量设置带过期时间的值,只有在全部设置成功的情况才更新过期时间
      *