|
@@ -13,6 +13,7 @@ import java.util.UUID;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import java.util.function.Function;
|
|
import java.util.function.Function;
|
|
import java.util.function.Supplier;
|
|
import java.util.function.Supplier;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
import com.chelvc.framework.base.context.ApplicationContextHolder;
|
|
import com.chelvc.framework.base.context.ApplicationContextHolder;
|
|
import com.chelvc.framework.base.function.Executor;
|
|
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]) " +
|
|
"else redis.call('SETEX', KEYS[1], ARGV[3], ARGV[2]) " +
|
|
"return redis.call('DECRBY', KEYS[1], ARGV[1]) end";
|
|
"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批量设值脚本(如果成功则更新过期时间)
|
|
* Redis批量设值脚本(如果成功则更新过期时间)
|
|
*/
|
|
*/
|
|
@@ -652,6 +660,36 @@ public class RedisUtils implements ApplicationContextAware {
|
|
return template.execute(script, Collections.singletonList(key), initialValue, duration.getSeconds());
|
|
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());
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* 批量设置带过期时间的值,只有在全部设置成功的情况才更新过期时间
|
|
* 批量设置带过期时间的值,只有在全部设置成功的情况才更新过期时间
|
|
*
|
|
*
|